如何创建可重用的实体框架投影表达式?
Posted
技术标签:
【中文标题】如何创建可重用的实体框架投影表达式?【英文标题】:How can I create a reusable Entity Framework projection expression? 【发布时间】:2016-04-18 17:51:59 【问题描述】:在我的数据库中,有几十列的表:
Table MyEntity:
int Id
string Name
string Email
...dozens of other columns I never use in this project
EF 生成的类具有这些额外列的属性,一个简单的查询获取所有这些额外的列,很浪费。
相反,我想要一个瘦的班级,像这样:
class MyEntity
public int Id;
public string Name;
public string Email;
当我查询时,我想创建我的瘦对象的实例,显然,我可以这样做:
from x in MyEntity
select new MyEntity Id = x.Id, Name = x.Name, Email = x.Email ;
但我经常这样做,每次输入属性都非常乏味(而且容易出错,因为我可能会忘记一个)。
所以我正在尝试做这样的事情:
from x in MyEntity
select x.ToLiteEntity();
但我不知道如何编写ToLiteEntity
以便它创建一个添加到查询中的表达式,以便它知道从数据库中只选择所需的列。我该怎么做?
【问题讨论】:
如果您根本不使用项目中的其他列,为什么要在项目中一开始就引用它们呢?还是它们在数据库中没有默认值,所以没有它们就无法创建新行? 因为 EF 模型生成器会创建它们。我可以删除它们,但有时我必须重新生成,我会丢失这些编辑。 如果您的数据库架构与您的 EF 模型不匹配,最好不要使用模型生成器。 您的所有实体都是从MyEntity
继承吗?
【参考方案1】:
您可以将其抽象到数据库之上的一层。当你想检索你的“精简”对象时,调用一个单独的方法:
public IQueryable<MyEntity> GetLiteMyEntities(DbContext c, string Name) // your implementation of DbContext, not actually DbContext
return from me in c.MyEntity
select new MyEntity Id = x.Id, Name = x.Name, Email = x.Email ;
编辑:如果您需要过滤不想返回的其他字段,您可以先编写过滤查询,然后使用 采用 IQueryable 的方法:
public IQueryable<MyEntity> GetLiteMyEntities(IQueryable<MyEntity> query)
return from me in query
select new MyEntity Id = x.Id, Name = x.Name, Email = x.Email ;
// build your filter first
from x in MyEntity
where x.someSpecialID == 42
select x;
// then pass it to get your lite object
var lite = GetLiteMyEntities(x);
更好的是,让它成为一个扩展方法:
public IQueryable<MyEntity> GetLiteMyEntities(this IQueryable<MyEntity> query)
return from me in query
select new MyEntity Id = x.Id, Name = x.Name, Email = x.Email ;
var lite = (from x in MyEntity
where x.someSpecialID == 42
select x).GetLiteMyEntities();
【讨论】:
这很好,虽然一个缺点是 Lite 对象不仅必须包含您想要返回的所有字段,还必须包含您可能想要在 Where 子句中使用但不能返回的任何字段。 @JoshuaFrank 查看我的编辑,您可以编写查询并使用它们,直到需要它才会执行(ToList
、迭代等)【参考方案2】:
您可以使用 AutoMapper 中的 Queryable Extensions
.ProjectTo() 将告诉 AutoMapper 的映射引擎 向 IQueryable 发出一个 select 子句,通知实体 只需要查询Item的Name列的框架 表,就像您手动将 IQueryable 投影到 带有 Select 子句的 OrderLineDTO。
【讨论】:
我在使用派生类(多态性)时遇到了这个问题。首先得到一个堆栈溢出异常,然后切换到使用 ProjectUsing 方法,但它无法使用抽象基类。以上是关于如何创建可重用的实体框架投影表达式?的主要内容,如果未能解决你的问题,请参考以下文章