Home > Backend Development > C++ > Can EF Core Code for Selecting Custom DTOs from Child Properties Be Reused Efficiently?

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

Linda Hamilton
Release: 2025-01-23 19:48:14
Original
859 people have browsed it

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

Can Code for Selecting a Custom DTO Object for a Child Property Be Reused with EF Core?

Entity Framework Core enables querying using expressions to convert to DTO objects. This functionality works well for the object and any child collections, as exemplified by the provided 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()
        };
}
Copy after login

And the Query:

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

However, the question arises: how can similar behavior be achieved for a child entity that is not a collection? For instance, if the Model class includes the property:

public AnotherChildModel AnotherChildModel { get; set; }
Copy after login

A conversion can be added to 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
        }
    };
Copy after login

But repeating this code every time the second child model needs to be converted to a DTO object is undesirable. Is there an alternative to using .Select() for a single entity?

Solutions

Several libraries offer an intuitive solution to this problem:

1. LINQKit:
With LINQKit, the .Select() operation can be applied to individual entities using the 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
        }
    };
Copy after login

The query can then be written as:

dbContext.Models
   .Where(m => SomeCriteria).Select(m => Model.AsDto(m))
   .AsExpandable()
   .ToList();
Copy after login

2. NeinLinq:
Similar to LINQKit, NeinLinq utilizes the InjectLambda attribute:

[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
        }
    };
Copy after login

The query can be modified as follows:

dbContext.Models
   .Where(m => SomeCriteria).Select(m => Model.AsDto(m))
   .ToInjectable()
   .ToList();
Copy after login

3. DelegateDecompiler:
DelegateDecompiler offers a concise approach using the Computed attribute:

[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
        }
    }
Copy after login

The query can be simplified to:

dbContext.Models
   .Where(m => SomeCriteria).Select(m => Model.AsDto(m))
   .Decompile()
   .ToList();
Copy after login

Each of these libraries accomplishes the goal by modifying the expression tree before EF Core processing, thereby avoiding the need for repeated code. Additionally, all three require a call to inject their respective IQueryProvider.

The above is the detailed content of Can EF Core Code for Selecting Custom DTOs from Child Properties Be Reused Efficiently?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template