我正在使用实体框架和Linq to Entities。我创建了一个小型数据库模式&实现版本控制和本地化的框架。每个实体现在由两个或三个表组成(即Product,ProductBase& ProductLocal)。
我的linq始终包含以下样板代码:
from o in DB.Product
from b in o.Base
from l in o.Local
WHERE o.VersionStatus == (int)VersionStatus.Active
&& b.VersionStatus == (int)VersionStatus.Active
&& l.VersionStatus == (int)VersionStatus.Active
&& l.VersionLanguage == Context.CurrentLanguage
select new ProductInstance { Instance = o, Base = b, Local = l }
我想要完成的是将上述内容变为:
(from o in DB.Product
from b in o.Base
from l in o.Local
select new ProductInstance { Instance = o, Base = b, Local = l }).IsActive()
或者最坏的情况是:
from o in DB.Product.Active()
from b in o.Base.Active()
from l in o.Local.Active()
select new ProductInstance { Instance = o, Base = b, Local = l }
我扩展了EDM生成的基类,以实现一些强制执行属性的接口(IVersionStatus和/或IVersionLanguage)。我是否可以通过某种方式遍历表达式树,检查表达式中的类型是否实现了该接口,然后相应地设置VersionStatus?
我喜欢它,就像第一个选项一样简单,只是少写和/或忘记。我已经看过在IEnumerable之后执行它的示例,但我宁愿不从数据库中获取比我需要的更多。
感谢您的任何提示!
答案 0 :(得分:3)
是
您可以通过在IQueryable上定义名为IsActive的扩展方法来完成此操作。 IQueryable上有一个名为“Expression”的属性,它返回一个表达式树,表示从查询中生成的LINQ方法调用链。
在你的情况下看起来像这样:
DB.Product.SelectMany(o=>o.base, (o, b)=>new{o.b}).SelectMany(item=>o.local, (item, local)=>new {item.o, item.b, item.local}).Select(item=>new ProductInstance { Instance = item.o, Base = item.b, Local=item.Local});
“DB.Product”是第一个From子句中的项目。每个剩余的“SelectMany”调用都是一个额外的from子句。
然后,您可以深入了解表达式树以收集所有from子句元素。查看它们的类型,然后最终为where子句生成表达式树。
然后,您的扩展方法将返回。使用您生成的where子句,它的IQueryable参数除外。
当您尝试“预测”结果时,生成的Where子句将在服务器上执行其余查询。
修改强>
请注意,如果您希望使用明确的“加入”子句,那么除了“SelectMany”之外,您还需要添加对“加入”方法的支持。
答案 1 :(得分:0)
您需要使用DataLoadOptions类,以便它自动加载您在该对象上指定的外键关系。这将使它自动获取您指定的链接表,这正是您正在做的事情。
此页面详细介绍了如何执行此操作并详细说明了我认为您正在寻找的内容。
http://www.crazysalsadancer.com/2008/08/efficient-data-loading-with-linq-using.html
答案 2 :(得分:0)
我可能错了,但我认为DataLoadOptions
不适用于实体框架。