【问题标题】:IQueryable<> from stored procedure (entity framework)IQueryable<> 来自存储过程(实体框架)
【发布时间】:2011-02-15 20:51:52
【问题描述】:

我想在执行存储过程时得到IQueryable&lt;&gt; 结果。

这是一段运行良好的代码:

IQueryable<SomeEntitiy> someEntities;  
var globbalyFilteredSomeEntities = 
  from se in m_Entities.SomeEntitiy
    where
      se.GlobalFilter == 1234 
  select se;

我可以使用它来应用全局过滤器,然后将结果用于:

result = globbalyFilteredSomeEntities
  .OrderByDescending(se => se.CreationDate)
  .Skip(500)
  .Take(10);

我想做的 - 在全局过滤器中使用一些存储过程。
我试过了:

将存储过程添加到m_Entities,但它返回IEnumerable&lt;&gt;并立即执行sp:

var globbalyFilteredSomeEntities = 
  from se in m_Entities.SomeEntitiyStoredProcedure(1234);

使用 EFExtensions 库实现查询,但它是 IEnumerable&lt;&gt;
如果我使用AsQueryable()OrderBy()Skip()Take()
然后ToList() 执行该查询 -
我收到 DataReader 已打开的异常,我需要先将其关闭(无法粘贴错误 - 它是俄语)。

var globbalyFilteredSomeEntities = 
  m_Entities.CreateStoreCommand("exec SomeEntitiyStoredProcedure(1234)")
            .Materialize<SomeEntitiy>();
            //.AsQueryable()
            //.OrderByDescending(se => se.CreationDate)
            //.Skip(500)
            //.Take(10)
            //.ToList();   

也只是跳过.AsQueryable() 没有帮助-同样的例外。
当我把ToList() 查询执行时,
但是没有Skip()Take(),执行查询代价太大。

【问题讨论】:

  • 这是 EF 4 吗?如果是这样,请使用ExecuteStoreQuery,然后您就不需要Materialize
  • 不,它是 EF 1,但如果 ExecuteStoreQuery 解决了我的问题,我会考虑迁移到 EF4。你能分享一些关于那个的特别文章的链接(如果你有的话)。
  • 我看到了stackoverflow.com/questions/2201369/…,据说ExecuteStoreQuery 返回ObjectResult 集合——与m_Entities.SomeEntitiyStoredProcedure(1234); 相同。所以看来ExecuteStoreQuery 不能解决我的问题。
  • 好的,我明白你在说什么。这 (Take()...) 是不可能的,因为如果 编写 SQL,则 EF 无法进一步编写该 SQL。但是,如果您确实使用ExecuteStoreQuery,那么您可以在您编写的SQL 中使用TOP 等。
  • ExecuteStoreQuery 返回 ObjectResult 还是返回 ObjectQuery?如果它返回 ObjectResult - 它对我来说是不可用的。

标签: .net entity-framework stored-procedures linq-to-entities iqueryable


【解决方案1】:

你不能做你想做的事,因为你不能把存储过程放在 SELECT 查询的 FROM 子句中 - SQL 不是为支持这种操作而构建的。

你能把你想要的逻辑放到视图中而不是存储过程中吗?

【讨论】:

  • 好主意。 EF 会从视图中返回相同类型的实体,还是我必须执行更多步骤才能实现?你能分享一些在 ef 中使用视图的代码 sn-p 吗?
  • 如果没有 EF,做他想做的事是没有问题的。
  • 很高兴看到 EF 中数据库视图的使用示例。如果没有 EF,我不感兴趣。
  • 在 .NET 4.5 和 EF5 中添加了对表值函数的支持。将您的存储过程更改为 TVF,您可以使用来自this answer 的代码。
【解决方案2】:

您可以使用我创建的名为 LinqToAnything 的项目,它允许您采用不可查询的数据访问方法并将其转换为 IQueryable。

我有一篇关于如何使用它的博文here

【讨论】:

    【解决方案3】:

    通常你可以使用 ToList() 解决这些问题

    var globbalyFilteredSomeEntities = m_Entities.CreateStoreCommand("exec SomeEntitiyStoredProcedure(1234)") 
                                                 .Materialize<SomeEntitiy>()
                                                 .ToList()  // <<-- added this.
                                                 .WhateverYouWant();
    

    为什么不能对可枚举执行 Skip() 和 Take()?这样做只会下载被跳过或采用的结果,不会读取其他结果。

    编辑:之前的版本在很多方面都存在明显错误。

    【讨论】:

    • 这不是我要找的。当我把ToList() 查询执行,但是没有Skip()Take() 执行查询太贵了。
    • AsEnumerable() 解决方案在这种情况下应该可以解决问题(编辑后)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 2013-03-19
    • 2016-09-18
    • 1970-01-01
    • 2011-03-13
    相关资源
    最近更新 更多