在LINQ中将映射对象分配给表达式结果到实体 [英] Assign Mapped Object to Expression Result in LINQ to Entities

查看:102
本文介绍了在LINQ中将映射对象分配给表达式结果到实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下子对象,我们使用表达式将实体"映射到域"模型.我们在专门调用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆