首页 > 后端开发 > C++ > 用于从子属性中选择自定义 DTO 的 EF Core 代码能否高效重用?

用于从子属性中选择自定义 DTO 的 EF Core 代码能否高效重用?

Linda Hamilton
发布: 2025-01-23 19:48:14
原创
859 人浏览过

Can EF Core Code for Selecting Custom DTOs from Child Properties Be Reused Efficiently?

为子属性选择自定义 DTO 对象的代码可以在 EF Core 中重用吗?

Entity Framework Core 支持使用表达式进行查询以转换为 DTO 对象。此功能适用于对象和任何子集合,如提供的模型所示:

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()
        };
}
登录后复制

和查询:

dbContext.Models.Where(m => SomeCriteria).Select(Model.AsDto).ToList();
登录后复制

但是,问题出现了:如何才能类似对于不是集合的子实体可以实现行为吗?例如,如果 Model 类包含属性:

public AnotherChildModel AnotherChildModel { get; set; }
登录后复制

可以将转换添加到表达式:

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
        }
    };
登录后复制

但是每次第二个子模型需要时都重复此代码转换为 DTO 对象是不可取的。对于单个实体,是否有使用 .Select() 的替代方法?

解决方案

几个库为这个问题提供了直观的解决方案:

1. LINQKit:
使用 LINQKit,.Select() 操作可以使用 ExpandableAttribute 应用于各个实体:

[Expandable(nameof(AsDtoImpl))]
public static ModelDto 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();
登录后复制

2。 NeinLinq:
与 LINQKit 类似,NeinLinq 使用 InjectLambda 属性:

[InjectLambda]
public static ModelDto 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();
登录后复制

3. DelegateDecompiler:
DelegateDecompiler 使用 Computed 属性提供了一种简洁的方法:

[Computed]
public static ModelDto 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();
登录后复制

每个库都实现了目标通过在 EF Core 处理之前修改表达式树,从而避免重复代码。此外,这三个都需要调用来注入各自的 IQueryProvider。

以上是用于从子属性中选择自定义 DTO 的 EF Core 代码能否高效重用?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板