it-swarm.com.de

Trennen von Domänenobjekt- und Datenmodellen

Ich habe viele Artikel, Blogs und SO Themen zum Trennen von Domänenobjekten und Datenmodellen) durchgesehen. Fast jede Antwort lautete: Sie sollten separate Klassen für die Domänen- und Datenpersistenz haben, weil .. .

Ich verstehe, warum es gut ist, aber ich habe kein Pseudo-Beispiel gefunden, um dieses Problem zu lösen, und ich habe folgende Gedanken - vielleicht weiß jeder, dass es auf diese Weise implementiert werden sollte, aber niemand tut es?

In meinen Lösungen verwende ich Automapper, um dies zu erreichen (Zuordnung der Domäne zum DB-Modell und der Domäne zu DTOs), aber ich möchte meinen Ansatz mit jedem anderen vergleichen, aber wie bereits erwähnt, kann ich kein gutes Beispiel finden.

Vielleicht gibt es nur Worte zu bewährten Methoden, die in realen, funktionierenden Anwendungen nicht vorhanden sind, und es ist einfacher, nur Domänenklassen als Datenmodelle zu verwenden, die von Formularen verwendet werden und viele Vorteile wie Caching oder Änderungsverfolgung bieten können.

Ich arbeite derzeit an einer Anwendung, in der Daten in der alten Datenbank gespeichert sind. Dieses Schema ... ist sehr schlecht. Die Verwendung von DB-Modellen als Domänenmodelle führt in diesem Fall dazu, dass auch meine Domäne nicht funktioniert.

Was denkst du darüber?

ORM-Funktionen && schnellerer Entwicklungsprozess> Trennung von Domänen- und Datenmodellen && langsamer Entwicklungsprozess?

4
bielu000

Schreiben Sie keine weitere Kopie Ihres Datenmodells in C # -Code, wenn Sie dieses Datenmodell bereits in der Datenbank haben. Was wäre der Punkt?

Konzentrieren Sie sich auf das eigentliche Problem, das darin besteht, dieses Datenmodell in der Datenbank dem Domänenmodell zuzuordnen.

ORMs machen das.

Der einzige Grund, kein ORM zu verwenden, besteht darin, dass Sie das Mapping noch besser durchführen können.

Was nicht unmöglich ist: Das Dapper "micro-ORM" ist sehr beliebt - es ist gut genug, um StackOverflow zu betreiben, und eignet sich hervorragend für viele Anwendungsfälle.

Wenn Sie sich für Micro-ORM (oder ADO oder Raw SQL) entscheiden, erstellen Sie möglicherweise DTO-Klassen, um die Daten zu speichern, die Sie aus der Datenbank erhalten. Das bedeutet jedoch nicht, dass Sie versuchen, ein Modell zu erstellen. (Und ja, für die Zuordnung zu und von DTOs ist AutoMapper an den meisten Stellen aufgetaucht, an denen ich in den letzten Jahren gearbeitet habe. Ich finde, dass es sehr schmerzhaft ist, Fehler im Automapper-Code aufzuspüren, aber vielleicht liegt das daran, dass es einfach zu verwenden ist und Missbrauch).

Ja zu einem separaten Datenmodell, aber Sie haben bereits eines . Ja zu einem ORM, wenn dies der billigste/effektivste Weg ist, Mapping durchzuführen.

Ich fand diesen Artikel - und einige der Kommentare - ziemlich scharfsinnig: Enterprisecraftsmanship mit-dem-Domain-Modell-getrennt-vom-Persistenz-Modell

3
Chris F Carroll

Ich habe mir ein NuGet-Paket ausgedacht, mit dem ich genau das tun kann, was Sie gesagt haben. Ich verwende den klassischen DDD-Ansatz:

  • Domain -> DataModel = AutoMapper
  • Domain -> DTO = AutoMapper
  • DataModel -> Domain = Factory
  • DTO -> Domain = Factory

Auf den ersten Blick scheint es ein verdammter Overkill zu sein, drei Modelle zu haben, aber es ermöglicht uns, die Domain zu entwerfen, ohne uns jemals um technische Probleme kümmern zu müssen, zum Beispiel schreibgeschützte Felder als private Setter festlegen zu müssen, weil das ORM ' t schreibgeschützte Felder usw. setzen.

Den gesamten Repository-Layer-Code finden Sie hier: https://github.com/DrMueller/MLH.DataAccess Derzeit wird eine MongoDB verwendet, aber das Muster ist ziemlich gleich. Ein Beispiel für die Verwendung finden Sie hier: https://github.com/DrMueller/MLH.WebApiExtensions

Wie es funktioniert:

Domänenmodell:

public class Individual : AggregateRoot
{
    public Individual(string id, string firstName, string lastName, DateTime birthdate)
        : base(id)
    {
        Guard.ObjectNotNull(() => firstName);
        Guard.ObjectNotNull(() => lastName);

        FirstName = firstName;
        LastName = lastName;
        Birthdate = birthdate;
    }

    public DateTime Birthdate { get; }
    public string FirstName { get; }
    public string LastName { get; }
}

erstellen Sie ein Repository für das Aggregatstammverzeichnis. Beispiel:

public class IndividualRepository : RepositoryBase<Individual, IndividualDataModel>
{
    public IndividualRepository(IDataModelRepository<IndividualDataModel> dataModelRepository, IDataModelAdapter<IndividualDataModel, Individual> dataModelAdapter) : base(dataModelRepository, dataModelAdapter)
    {
    }
}

Ein Datenmodell, das die "Entität" darstellt:

public class IndividualDataModel : DataModelBase
{
    public DateTime Birthdate { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Und ein DataModelAdapter, der in beide Richtungen abbildet:

public class IndividualDataModelAdapter : DataModelAdapterBase<IndividualDataModel, Individual>
{
    private readonly IIndividualFactory _individualFactory;

    public IndividualDataModelAdapter(IIndividualFactory individualFactory, IMapper mapper) : base(mapper)
    {
        _individualFactory = individualFactory;
    }

    public override Individual Adapt(IndividualDataModel dataModel)
    {
        return _individualFactory.Create(
            dataModel.FirstName,
            dataModel.LastName,
            dataModel.Birthdate,
            dataModel.Id);
    }
}

Das ist so ziemlich alles, die Implementierung des Repositorys hat Zugriff auf das Datenmodell und die abfragbaren Dateien, und die Schnittstelle funktioniert nur mit den Domänenmodellen.

Um Ihre Frage zu beantworten: Der Infrastrukturcode kann einfach so allgemein gestaltet werden, dass es zu minimalen Verzögerungen kommt. Alles, was Sie tun müssen, ist, die Möglichkeit beizubehalten, das Mapping zu definieren und es für spezielle Anforderungen zu überschreiben.

0