在LINQ中将映射对象分配给表达式结果到实体 [英] Assign Mapped Object to Expression Result in LINQ to Entities
问题描述
我有以下子对象,我们使用表达式将实体"映射到域"模型.我们在专门调用ChildRecordService方法GetChild或GetChildren时使用此方法:
I have the following child object that we use an expression to map our 'entity' to our 'domain' model. We use this when specifically calling our ChildRecordService method GetChild or GetChildren:
public static Expression<Func<global::Database.Models.ChildRecord, ChildRecord>> MapChildRecordToCommon = entity => new ChildRecord
{
DateTime = entity.DateTime,
Type = entity.Type,
};
public static async Task<List<ChildRecord>> ToCommonListAsync(this IQueryable<global::Database.Models.ChildRecord> childRecords)
{
var items = await
childRecords.Select(MapChildRecordToCommon).ToListAsync().EscapeContext();
return items;
}
public async Task<List<ChildRecord>> GetChildRecords()
{
using (var uow = this.UnitOfWorkFactory.CreateReadOnly())
{
var childRecords= await uow.GetRepository<IChildRecordRepository>().GetChildRecords().ToCommonListAsync().EscapeContext();
return childRecords;
}
}
一切正常.但是,我们还有另一个对象是该孩子的父母,在某些情况下,我们也希望在实现和映射过程中得到孩子.
So that all works just fine. However we have another object that is a parent to that child, that in SOME cases, we also wish to get the child during the materialisation and mapping process.
换句话说,标准对象看起来像这样:
In other words the standard object looks as such:
private static Expression<Func<global::Database.Models.Plot, Plot>> MapPlotToCommonBasic = (entity) => new Plot
{
Id = entity.Id,
Direction = entity.Direction,
Utc = entity.Utc,
Velocity = entity.Velocity,
};
但是,我还想映射的是Plot.ChildRecord属性,使用我已经创建的表达式MapChildRecordToCommon.我做了第二个表达只是为了测试这个:
However what I also want to map is the Plot.ChildRecord property, using the expression MapChildRecordToCommon I have already created. I made a second expression just to test this:
private static Expression<Func<global::Database.Models.Plot, Plot>> MapPlotToCommonAdvanced = (entity) => new Plot
{
ChildRecord = MapChildRecordToCommon.Compile() (entity.ChildRecord)
};
此操作失败:
System.NotSupportedException
The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
是否有一种方法可以对ChildRecord重用我现有的表达式,以在Plot对象上实现ChildRecord的对象(即一对一/单数而不是多个)?我认为我的麻烦是由于只有一个对象而无法使用.Select(Map)方法引起的.我不太擅长表达,并且为此碰壁.
Is there a way to reuse my existing expression for ChildRecord, to materialise the object of ChildRecord (ie. one to one/singular not multiple) on the Plot object? I think my trouble is caused by there being just one object and being unable to use the .Select(Map) method. I am not too great at expressions and have hit a wall with this.
作为参考,"Plot"对象上实际上还有多达5或6个其他子对象,我也想为其创建表达式.
For reference, there are actually up to 5 or 6 other child objects on the "Plot" object that I also want to make expressions for.
推荐答案
我通过使用第三方库LinqKit解决了这个问题.
I resolved this by using the third party library LinqKit.
该库允许使用2种方法:.AsExpandable()(允许表达式正确编译并按照我的理解被调用),. Invoke()作为表达式的扩展方法,而不是调用Expression .调用(您的表情).我提供了一个空检查,以防万一.
The library allowed the use of 2 methods, .AsExpandable() (which allows for the expressions to properly compile and be invoked as I understand), and .Invoke() as an extension method to an expression, rather than calling Expression.Invoke(yourexpression). I included a null check just in case.
我的代码现在如下所示:
My code now looks as follows:
public static async Task<List<Plot>> ToCommonListAsync(this IQueryable<global::Database.Models.Plot> plots)
{
var items = await
plots.AsExpandable().Select(MapPlotToCommon).ToListAsync().EscapeContext();
return items;
}
private static Expression<Func<global::Database.Models.Plot, Plot>> MapPlotToCommon = (entity) => new Plot
{
Id = entity.Id,
Direction = entity.Direction,
Utc = entity.Utc,
Velocity = entity.Velocity,
ChildRecord = entity.ChildRecord != null ? MapChildRecordToCommon.Invoke(entity.ChildRecord) : default
};
public static Expression<Func<global::Database.Models.ChildRecord, ChildRecord>> MapChildRecordToCommon = entity => new ChildRecord
{
DateTime = entity.DateTime,
Type = entity.Type,
};
这篇关于在LINQ中将映射对象分配给表达式结果到实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!