简体   繁体   English

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

[英]How can I create a reusable Entity Framework projection expression?

In my database, there are tables with dozens of columns: 在我的数据库中,有几十列的表:

Table MyEntity: int Id string Name string Email ...dozens of other columns I never use in this project

The class generated by EF has properties for those extra columns, and a simple query gets all those extra columns, wastefully. EF生成的类具有这些额外列的属性,而简单查询会浪费所有这些额外列。

Instead, I want to have a thin class, like so: 相反,我想要一个瘦的类,如下所示:

class MyEntity { public int Id; public string Name; public string Email; }

When I query, I want to create instances of my thin object, and obviously, I can do this: 当我查询时,我想创建我的瘦对象的实例,显然,我可以这样做:

from x in MyEntity
select new MyEntity {Id = x.Id, Name = x.Name, Email = x.Email };

But I do this a lot, and typing out the properties every time gets very tedious (and error prone, because I could forget one). 但是我做了很多,每次输入属性变得非常乏味(并且容易出错,因为我可以忘记一个)。

So I'm trying to do something like this instead: 所以我试着这样做:

from x in MyEntity
select x.ToLiteEntity();

But I'm not sure how to write ToLiteEntity so that it creates an expression that gets added to the query, so that it knows to select only the needed columns from the database. 但我不确定如何编写ToLiteEntity以便创建一个添加到查询中的表达式 ,以便它知道只从数据库中选择所需的列。 How can I do this? 我怎样才能做到这一点?

You can abstract this to a layer above the database. 您可以将其抽象为数据库上方的图层。 When you want to retrieve your 'lite' objects, call a separate method: 如果要检索“lite”对象,请调用单独的方法:

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 };
}

EDIT: If you need to filter on other fields that you don't want to return, you can compose your filter query first, and then use a method that takes an IQueryable: 编辑:如果您需要过滤不想返回的其他字段,可以先编写过滤查询,然后使用一个 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);

Even better, make it an extension method: 更好的是,使它成为一种扩展方法:

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();

You may use Queryable Extensions from AutoMapper 您可以使用AutoMapper中的Queryable Extensions

The .ProjectTo() will tell AutoMapper's mapping engine to emit a select clause to the IQueryable that will inform entity framework that it only needs to query the Name column of the Item table, same as if you manually projected your IQueryable to an OrderLineDTO with a Select clause. .ProjectTo()将告诉AutoMapper的映射引擎向IQueryable发出一个select子句,该子句将通知实体框架它只需要查询Item表的Name列,就像手动将IQueryable手动投影到OrderLineDTO一样。选择条款。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM