在EntityFramework中使用SqlQuery来构成真正的IQueryable
有没有办法让SqlQuery或任何其他sql执行方法组成一个模型对象,并允许像Include这样的方法工作? 我这样做(其中view_products是一个SQL表函数):
var p = context.SqlQuery("select * from view_products(@param1)", new SqlParameter("param1", "somevalue"));
我想这样做:
var list = p.Include(i => i.Inventories).ToList();
这让我得到了一个DbRawSqlQuery。 这个我不能“包含”,因为你不能在DbRawSqlQuery上做到这一点。 所以,我最后添加一个AsQueryable,如:
var p = context.SqlQuery("select * from view_products(@param1)", new SqlParameter("param1", "somevalue")).AsQueryable();
但是,我知道这真的给了我一个IEnumerable,所以.Include不会产生任何结果。
我正在寻找另一种方法的建议,我从SQL函数中获取我的产品,然后加载其相关的Inventory对象,以便我有一个对象图。 谢谢!
SqlQuery
提出了一些我还没有意识到的问题。
不包括在内
您正确解释了为什么Include
在将IEnumerable
转换为IQueryable
后没有任何效果。 Include
扩展了一个表达式,并且IEnumerable
没有表达式(并且在将它转换为IQueryable
后不会神奇地获得一个表达式)。
没有附加没有延迟加载
因此,您最终得到的Product
列表未附加到上下文中,并且无法进行延迟加载 。 您必须明确地将Product
附加到上下文(例如,通过将其状态设置为Unchanged
)以使其延迟加载。
这是我刚刚发现的,而且很奇怪。 实体被实现为代理对象,但与DbSet.AsNoTracking()
提取的分离实体相反,它们不显示延迟加载。 我认为这是一个错误,我报告了它。
但延迟加载会导致n + 1查询反模式:分别为每个产品获取Inventory对象的查询。 因此,这不是获取对象图的最佳方式。
没有关系修复
所以你真正想要的是一次性加载属于这些产品的所有Inventory对象,让关系fixup完成它的工作(即EF自动填充所有Product.Inventories
集合):
context.Inventories.Where(i => productIds.Contains(i.ProductId)).Load();
…其中productIds
是p
中的procuct ID列表。
但是,关系修正仅适用于附加实体,因此,您必须明确地将其状态Unchanged
为“未Unchanged
。 如果你这样做,你就准备好了…除非你没有。
DbSet.AsNoTracking()
获取的分离实体再次存在差异。 后者响应关系修复,来自SqlQuery
那些没有!
(相反)精心设计的解决方案
剩下的就是:加载上面显示的相关Inventory
对象并自己填充Product.Inventories
集合:
var query = from product in p join inv context.Inventories.Local on product.ProductId equals inv.ProductId into inventories select new { product, inventories } foreach(var anon in query) { anon.product.Inventories = anon.inventories.ToList(); }
当然这完全不能令人满意。
上述就是C#学习教程:在EntityFramework中使用SqlQuery来构成真正的IQueryable分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1013079.html