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

There are several libraries which allows to do that in intuitive way:

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();

UPDATE: For EF Core, LINQKit can be confugred globally and AsExpanding() can be omitted.

builder
    .UseSqlServer(connectionString)
    .WithExpressionExpanding(); // enabling LINQKit extension

NeinLinq – almost the same as in 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();

UPDATE: For EF Core, NenLinq can be confugred globally and ToInjectable() can be omitted.

builder
    .UseSqlServer(connectionString)
    .WithLambdaInjection(); // enabling NeinLinq extension

DelegateDecompiler – less verbose than others

[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. All of them need additional call to inject it’s own IQueryProvider.

Leave a Comment