如何创建可重用的Entity Framework投影表达式?

4
在我的数据库中,有一些表格有数十个列: 表格 MyEntity: int Id string Name string Email ...还有其他几十个在这个项目中从未使用的列 由 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,以便创建一个表达式,将其添加到查询中,以便它知道仅从数据库中选择所需的列。我该怎么做?


如果你的项目中从未使用其他列,为什么一开始就要引用它们呢?或者它们在数据库中没有默认值,所以你不能创建没有这些列的新行? - Jon Hanna
因为 EF 模型生成器会创建它们。我可以删除它们,但有时我需要重新生成,那么我就会失去这些编辑。 - Joshua Frank
如果您的数据库模式与EF模型不匹配,最好不要使用模型生成器。 - Jon Hanna
你的所有实体类都继承自MyEntity类吗? - haim770
2个回答

2
您可以将其抽象化到数据库上面一层。当您想要检索“简化”对象时,请调用单独的方法:
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子句中使用但不返回的字段。 - Joshua Frank
@JoshuaFrank,看一下我的编辑。你可以组合查询并使用它们,直到需要执行(例如 ToList,迭代等)时才会执行。 - DrewJordan

1
你可以使用AutoMapper的Queryable Extensions
.ProjectTo()将告诉AutoMapper的映射引擎向IQueryable发出选择子句,以通知实体框架它只需要查询Item表的Name列,就像手动将IQueryable投影到带有Select子句的OrderLineDTO一样。

当我使用派生类(多态)时,遇到了问题。首先出现了堆栈溢出异常,然后切换到使用ProjectUsing方法,但它无法与抽象基类一起使用。 - Rob Kent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接