[英]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:有几个库允许以直观的方式做到这一点:
[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.