【问题标题】: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继承吗?

标签: c# .net entity-framework linq-to-entities entity-framework-6


【解决方案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 方法,但它无法使用抽象基类。
猜你喜欢
  • 1970-01-01
  • 2010-09-13
  • 1970-01-01
  • 1970-01-01
  • 2016-05-22
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多