简体   繁体   English

我可以重复使用代码来为具有 EF Core 的子属性选择自定义 DTO object 吗?

[英]Can I reuse code for selecting a custom DTO object for a child property with EF Core?

When querying using Entity Framework Core, I am using expressions to convert to DTO objects, which works well for the object, and any child collections.使用 Entity Framework Core 进行查询时,我使用表达式转换为 DTO 对象,这适用于 object 和任何子 collections。

A simplified example:一个简化的例子:

Model: Model:

public class Model
{
    public int ModelId { get; set; }
    public string ModelName { get; set; }

    public virtual ICollection<ChildModel> ChildModels { get; set; }

    // Other properties, collections, etc.

    public static Expression<Func<Model, ModelDto>> AsDto =>
        model => new ModelDto
        { 
            ModelId = model.ModelId,
            ModelName = model.ModelName,
            ChildModels = model.ChildModels.AsQueryable().Select(ChildModel.AsDto).ToList()
        };
}

Query:询问:

dbContext.Models.Where(m => SomeCriteria).Select(Model.AsDto).ToList();

My question is about trying to find a way to do something similar for a child that is not a collection.我的问题是关于试图找到一种方法来为一个不是集合的孩子做类似的事情。 If I have added to my model:如果我已添加到我的 model:

public AnotherChildModel AnotherChildModel { get; set; }

I can add a conversion in the expression:我可以在表达式中添加转换:

public static Expression<Func<Model, ModelDto>> AsDto =>
    model => new ModelDto
    { 
        ModelId = model.ModelId,
        ModelName = model.ModelName,
        ChildModels = model.ChildModels.AsQueryable().Select(ChildModel.AsDto).ToList(),
        AnotherChildModel = new AnotherChildModelDto
        {
            AnotherChildModelId = model.AnotherChildModelId
        }
    };

But, I have not found a good way to avoid repeating this code every time that I need to convert the second child model to a DTO object.但是,每次我需要将第二个孩子 model 转换为 DTO object 时,我都没有找到避免重复此代码的好方法。 The expressions work for the main object and any child collections, but not for single entities.这些表达式适用于主 object 和任何子 collections,但不适用于单个实体。 Is there a way to add the equivalent of a.Select() for a single entity?有没有办法为单个实体添加等效的 a.Select() ?

There are several libraries which allows to do that in intuitive way:有几个库允许以直观的方式做到这一点:

LINQKit LINQKit

[Expandable(nameof(AsDtoImpl))]
public static AsDto(Model model)
{
   _asDtoImpl ??= AsDtoImpl() .Compile();
   return _asDtoImpl(model);
}

private static Func<Model, ModelDto> _asDtoImpl;

private static Expression<Func<Model, ModelDto>> AsDtoImpl =>
    model => new ModelDto
    { 
        ModelId = model.ModelId,
        ModelName = model.ModelName,
        ChildModels = model.ChildModels.AsQueryable().Select(ChildModel.AsDto).ToList(),
        AnotherChildModel = new AnotherChildModelDto
        {
            AnotherChildModelId = model.AnotherChildModelId
        }
    };
dbContext.Models
   .Where(m => SomeCriteria).Select(m => Model.AsDto(m))
   .AsExpandable()
   .ToList();

NeinLinq - almost the same as in LINQKit NeinLinq - 与 LINQKit 中的几乎相同

[InjectLambda]
public static AsDto(Model model)
{
   _asDto ??= AsDto() .Compile();
   return _asDto(model);
}

private static Func<Model, ModelDto> _asDto;

private static Expression<Func<Model, ModelDto>> AsDto =>
    model => new ModelDto
    { 
        ModelId = model.ModelId,
        ModelName = model.ModelName,
        ChildModels = model.ChildModels.AsQueryable().Select(ChildModel.AsDto).ToList(),
        AnotherChildModel = new AnotherChildModelDto
        {
            AnotherChildModelId = model.AnotherChildModelId
        }
    };
dbContext.Models
   .Where(m => SomeCriteria).Select(m => Model.AsDto(m))
   .ToInjectable()
   .ToList();

DelegateDecompiler - less verbose than others DelegateDecompiler - 不那么冗长

[Compute]
public static AsDto(Model model)
  => new ModelDto
    { 
        ModelId = model.ModelId,
        ModelName = model.ModelName,
        ChildModels = model.ChildModels.AsQueryable().Select(ChildModel.AsDto).ToList(),
        AnotherChildModel = new AnotherChildModelDto
        {
            AnotherChildModelId = model.AnotherChildModelId
        }
    }
dbContext.Models
   .Where(m => SomeCriteria).Select(m => Model.AsDto(m))
   .Decompile()
   .ToList();

All libraries do the same thing - correct expression tree before EF Core processing.所有库都做同样的事情 - 在 EF Core 处理之前更正表达式树。 All of them need additional call to inject it's own IQueryProvider .他们都需要额外的调用来注入它自己的IQueryProvider

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

相关问题 我如何首先使用可重用的查询/表达式和EF代码在父级中获取子实体作为DTO? - How can I fetch child entities as DTO in parent using reusable queries/Expression's with EF code first? 使用不同的子/嵌套 object 重用 DTO - Reuse DTO with different child/nested object EF Core 5 - 如何将 EF.Functions.Like 与映射到 JSON 字符串的自定义属性一起使用? - EF Core 5 - How can I use EF.Functions.Like with a custom property that maps to a JSON string? 无法使用 VS Code 在 WebAPI、DTO、AutoMapper 和 .NET Core 中检索 EF 外键值 - Can't retrieve EF Foreign Key values in WebAPI, DTO, AutoMapper and .NET Core using VS Code EF Core 查询和投影到 dto 不填充属性 - EF Core query and projection to dto doesn't fill the property 如何在EF中移动具有导航属性的子对象 - How do I move a child object with navigation property in EF 如何首先使用带有EF代码的wcf数据服务公开dto对象? - How can i expose dto objects using wcf data service with ef code first? 将列映射到 EF Core 3 中的子对象 - Map column to child object in EF Core 3 EF核心FromSql自定义属性绑定 - EF core FromSql custom property binding 如何通过代码直接使用 EF Core Migrations API - How can I use EF Core Migrations API directly by code
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM