让存储过程返回IQueryable <t>而不是ObjectResult <telement>

时间:2015-07-25 12:45:39

标签: linq entity-framework stored-procedures

我希望能够使用存储过程使用这种查询,因为我使用简单的DbSet<Balance>

var bals = db.Balances
              .Where(b => db.Balances.Any(b2 => b.Number.StartsWith(b2.Number)&&b2.Number!=b.Number))
              .ToList();

这可行但是当我使用存储过程中的导入函数尝试它时:

var bals = db.GetCustomBalances("2015")
             .Where(b => db.Balances
                           .Any(b2 => b.Number.StartsWith(b2.Number)&&b2.Number!=b.Number))
             .ToList();

这不起作用:

  

不能多次枚举可枚举

如何解决这个问题?

更新

我注意到问题是因为存储过程调用db.GetCustomBalances("2015")返回ObjectResult<TElement>而不是IQueryable<TElement>,而不是DbSet<TableName>

如何让存储过程返回IQueryable<T>而不是ObjectResult<TElement>

1 个答案:

答案 0 :(得分:1)

如果你真的想这样做,你可以使用一个技巧:打开一个事务,创建一个临时表(sql server中的#表)通过将结果直接插入到临时表中来执行该过程(使用ExecuteStoreCommand执行该操作) api但我会首先使用接口来抽象和隔离它,这样如果你改变你的SGBD,你也可以改变这个sql语句)还有什么可以做的是将临时表以某种方式映射到上下文实体才能够与sp结果集建立联接。我之前通过使用另一个技巧完成了这个:创建一个与存储过程结果具有相同模式的伪表,将其映射到实体框架中并使用该表进行连接。但是您必须挂钩执行的sql以将表名替换为临时表名。您可以通过实现IDbCommandInterceptor并在将DbCommand commandText发送到数据库服务器之前对其进行操作来实现。有关它的更多详细信息,请在此处找到:http://www.skylinetechnologies.com/Blog/Article/2394/Entity-Framework-60-Intercepting-SQL-produced-by-EF.aspx请记住,此解决方案不依赖于sql server,因为几乎所有SGBD都具有临时表,您可以创建一个为每个SGBD提供程序提供IDbCommandInterceptor的抽象工厂。另外要记住的一点是:如果重用相同的连接,请记住删除临时表,否则您不必费心,因为每次sql连接返回池时,都会为该连接调用连接清理机制。例如,在sql server中调用sp_resetconnection