实体框架6投影,POCO实体返回类型

时间:2016-03-23 20:19:34

标签: c# entity-framework entity projection

背景信息:我有一个包含3个项目的解决方案

Project.Db:包含我的dbContext / Repositories
Project.Core:包含我的POCO类(由dbContext使用) Project.Web:我的mvc项目,它包含viewModels和POCO-ViewModel映射类。

似乎不可能让类型化投影返回EF实体类型。 在Project.Db中,我有以下方法。我想获得区域及其子区域的两个特定字段(名称和ID)。我不希望生成的T-SQL选择不需要的字段。

public List<Region> GetRegionsAndSubRegions(){
var regions = Context.Regions.Where(r => condition);
var lightRegions = regions.Select(z => new Region{
                                      RegionName = z.RegionName,
                                      RegionId = z.RegionId
                                  }).ToList();
}

这会让我错误

The entity or complex type 'Region' cannot be constructed in a LINQ to Entities query.

我找到的方式就是:

var lightRegions = regions.ToList().Select(z => new Region{
                                      RegionName = z.RegionName,
                                      RegionId = z.RegionId
                                  }).ToList();

然而,&#34; ToList()&#34;将选择我不想要的所有字段。

我可以投射到ViewModel类,但我不想在Project.Db中使用该依赖项。该方法应返回我的POCO实体列表(列表<Region&gt;)。

我的所有存储库方法都将Core(POCO)类型的对象返回给Web项目。

有没有办法在不投射到匿名类型的情况下将其映射回区域类型(这将是多余的)?感谢

2 个答案:

答案 0 :(得分:1)

这是可能的。我刚刚用它做了 <package id="EntityFramework" version="6.1.3" targetFramework="net461" />

车辆(模型和数据库中30多个字段)投射到StatisticsVehicle。

我的查询:

var vehicles = 
    _context.Vehicles
        .Select(v => 
            new StatisticsVehicle()
            {
                PlateNumber = v.PlateNumber,
                StatisticsVehicleProcesses = 
                    v.VehicleProcesses.Select(vp => new StatisticsVehicleProcess()
                    {
                        EffectiveIssuanceDate = vp.EffectiveIssuanceDate,
                        PlannedIntakeEndDate = vp.PlannedIntakeEndDate
                    })
            }
        )
        .ToList();

这导致sql查询仅从该车辆和车辆进程中选择我需要的字段:

SELECT 
    [Project2].[Id] AS [Id], 
    [Project2].[C1] AS [C1], 
    [Project2].[PlateNumber] AS [PlateNumber], 
    [Project2].[C2] AS [C2], 
    [Project2].[EffectiveIssuanceDate] AS [EffectiveIssuanceDate], 
    [Project2].[PlannedIntakeEndDate] AS [PlannedIntakeEndDate]
    FROM ...

答案 1 :(得分:0)

无法在投影中直接实例化EF实体类型。我认为这是为了防止像格特所说的歧义。要做到这一点的唯一方法是 将项目设置为匿名类型,然后映射到实体类型。

public List<Region> GetRegionsAndSubRegions(){
var regions = Context.Regions.Where(r => condition);
var anonRegions = regions.Select(r => new {
                                  RegionName = r.RegionName,
                                  RegionId = r.RegionId
                              }).ToList();
var lightRegions = anonRegions.Select(r => new Region{
                                  RegionName = r.RegionName,
                                  RegionId = r.RegionId
                              }).ToList();
}

当然,这是一种颈部疼痛,并且通过很多桌面关系变得非常丑陋。