3

我正在使用实体框架和 Linq to Entity。我创建了一个小型数据库模式和框架来实现版本控制和本地化。现在每个实体都包含两个或三个表(即 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 之后,但我宁愿不要从数据库中提取比我需要的更多的东西。

感谢您的任何提示!

4

3 回答 3

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 。

当您尝试“foreach”结果时,生成的 Where 子句将在服务器上与查询的其余部分一起执行。

编辑:

请注意,如果您希望它与显式的“Join”子句一起使用,那么除了“SelectMany”之外,您还需要添加对“Join”方法的支持。

于 2008-10-20T01:22:39.483 回答
0

您需要使用 DataLoadOptions 类,以便它自动加载您在该对象上指定的外键关系。这将使它自动获取您指定的链接表,这正是您正在做的事情。

此页面详细说明了如何执行此操作,并详细说明了我认为您正在寻找的内容。

http://www.crazysalsadancer.com/2008/08/efficient-data-loading-with-linq-using.html

于 2008-10-20T01:08:42.677 回答
0

我可能是错的,但我不认为DataLoadOptions适用于实体框架。

于 2008-10-20T01:18:54.903 回答