Heim >Backend-Entwicklung >C++ >Kann EF-Core-Code zur Auswahl benutzerdefinierter DTOs aus untergeordneten Eigenschaften effizient wiederverwendet werden?

Kann EF-Core-Code zur Auswahl benutzerdefinierter DTOs aus untergeordneten Eigenschaften effizient wiederverwendet werden?

Linda Hamilton
Linda HamiltonOriginal
2025-01-23 19:48:14916Durchsuche

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

Kann Code zum Auswählen eines benutzerdefinierten DTO-Objekts für eine untergeordnete Eigenschaft mit EF Core wiederverwendet werden?

Entity Framework Core ermöglicht Abfragen mithilfe von Ausdrücken zur Konvertierung in DTO-Objekte. Diese Funktionalität funktioniert gut für das Objekt und alle untergeordneten Sammlungen, wie am Beispiel des bereitgestellten Modells:

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

Und der Abfrage:

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

Es stellt sich jedoch die Frage: Wie kann ähnliches erfolgen? Kann ein Verhalten für eine untergeordnete Entität erreicht werden, die keine Sammlung ist? Wenn die Model-Klasse beispielsweise die Eigenschaft enthält:

public AnotherChildModel AnotherChildModel { get; set; }

Eine Konvertierung kann dem Ausdruck hinzugefügt werden:

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

Dieser Code wird jedoch jedes Mal wiederholt, wenn das zweite untergeordnete Modell dies erfordert in ein DTO-Objekt konvertiert werden soll, ist unerwünscht. Gibt es eine Alternative zur Verwendung von .Select() für eine einzelne Entität?

Lösungen

Mehrere Bibliotheken bieten eine intuitive Lösung für dieses Problem:

1. LINQKit:
Mit LINQKit kann die .Select()-Operation mithilfe des ExpandableAttribute: auf einzelne Entitäten angewendet werden:

[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
        }
    };

Die Abfrage kann dann wie folgt geschrieben werden:

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

2. NeinLinq:
Ähnlich wie LINQKit verwendet NeinLinq das InjectLambda-Attribut:

[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
        }
    };

Die Abfrage kann wie folgt geändert werden:

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

3. DelegateDecompiler:
DelegateDecompiler bietet einen prägnanten Ansatz unter Verwendung des Computed-Attributs:

[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
        }
    }

Die Abfrage kann wie folgt vereinfacht werden:

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

Jede dieser Bibliotheken erreicht das Ziel durch Ändern des Ausdrucksbaums vor der EF Core-Verarbeitung, wodurch die Notwendigkeit für wiederholten Code vermieden wird. Darüber hinaus benötigen alle drei einen Aufruf, um ihren jeweiligen IQueryProvider einzufügen.

Das obige ist der detaillierte Inhalt vonKann EF-Core-Code zur Auswahl benutzerdefinierter DTOs aus untergeordneten Eigenschaften effizient wiederverwendet werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn