Maison >développement back-end >C++ >Le code EF Core pour la sélection de DTO personnalisés à partir des propriétés enfants peut-il être réutilisé efficacement ?

Le code EF Core pour la sélection de DTO personnalisés à partir des propriétés enfants peut-il être réutilisé efficacement ?

Linda Hamilton
Linda Hamiltonoriginal
2025-01-23 19:48:14914parcourir

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

Le code permettant de sélectionner un objet DTO personnalisé pour une propriété enfant peut-il être réutilisé avec EF Core ?

Entity Framework Core permet d'effectuer des requêtes à l'aide d'expressions à convertir en objets DTO. Cette fonctionnalité fonctionne bien pour l'objet et toutes les collections enfants, comme en témoigne le modèle fourni :

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

Et la requête :

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

Cependant, la question se pose : comment des similaires peuvent-ils le comportement peut-il être atteint pour une entité enfant qui n'est pas une collection ? Par exemple, si la classe Model inclut la propriété :

public AnotherChildModel AnotherChildModel { get; set; }

Une conversion peut être ajoutée à l'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
        }
    };

Mais répéter ce code à chaque fois que le deuxième modèle enfant doit être converti en objet DTO n'est pas souhaitable. Existe-t-il une alternative à l'utilisation de .Select() pour une seule entité ?

Solutions

Plusieurs bibliothèques offrent une solution intuitive à ce problème :

1. LINQKit :
Avec LINQKit, l'opération .Select() peut être appliquée à des entités individuelles à l'aide de 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
        }
    };

La requête peut ensuite être écrite comme :

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

2. NeinLinq :
Semblable à LINQKit, NeinLinq utilise l'attribut 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
        }
    };

La requête peut être modifiée comme suit :

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

3. DelegateDecompiler :
DelegateDecompiler propose une approche concise en utilisant l'attribut 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
        }
    }

La requête peut être simplifiée en :

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

Chacune de ces bibliothèques atteint l'objectif en modifiant l'arborescence d'expression avant le traitement EF Core, évitant ainsi le besoin de code répété. De plus, tous les trois nécessitent un appel pour injecter leur IQueryProvider respectif.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn