2009-08-24 6 views
6

Ich habe mit linq2sql und der Linq DTOs (den Klassen, die von linq2sql erstellt werden) ....Verwechslung zwischen DTOs (linq2sql) und Klassenobjekten!

ich verwirrt bin, habe ich die Aufgabe, die Aktualisierung eine alte Anwendung, und ich kann sehen, dass mein DTOs erfolgreich arbeiten wird verwendet, wie sie sein sollten .... zum Transportdatum

Ich verwende das Repository-Muster, also übertrage ich Daten vom Repository zum Dienst über die linq2sql dtos ... sobald ich in der Service-Schicht bin (das ist im Grunde meine Geschäftslogik), dann muss ich Klassenobjekte weitergeben.

Diese Klassenobjekte sind grundsätzlich ein Spiegelbild (mehr oder weniger) der dtos - es gibt so etwas Ich ändere an einer Stelle, aber im Allgemeinen die gleiche ..

So zurück zu der Frage in der Hand! - ist es eine gute Vorgehensweise, dtos nur zum Transport von Daten vom Repository zur Serviceebene zu verwenden ... und sobald ich in der Serviceebene (Geschäftslogik) bin, sollte ich alle meine dtos zu den Klassenobjektgegenstücken MAPPING (natürlich mit automapper! !)

Meine andere Alternative ist, weiterhin die DTOS wie Klassenobjekte zu verwenden und sie von Methode zu Methode und als Rückgabetypen usw. weiterzuleiten, aber ich fühle, dass das eine schlechte Übung ist und ich laufe in Kreisen herum und frage mich, welche Methode ich sollte gelten?

Jede Hilfe wirklich zu schätzen

dank

Antwort

5

Hier ist meine Meinung: Beim Umgang mit jeder nicht-Trival-Anwendung. Die Verwendung Ihrer linq2Sql-Objekte als Ihr Domänenmodell ist eine wirklich schlechte Idee. Ich sehe linq2Sql als ORM und nichts mehr. Datenbanken (mit denen linq2Sql direkt korrespondiert) sind eine Normalisierung von Daten. Klassen (im OOAD-Sinn) sind eine Normalisierung von Verhalten (keine Daten).

[diese Klasse Objekte sind im Grunde ein Spiegelbild] ...

ich dies auf, wenn Anwendungen mit Linq2Sql Aufbau. Lasst uns realistisch sein ... Die meisten Geschäftsanwendungen sind verherrlichte CRUD-Anwendungen. Es ist daher nicht ausgeschlossen, dass ein großer Prozentsatz der Entitäten Ihrer Anwendung direkt den Datenbanktabellen entspricht. Ich wollte nicht direkt an die DTO's gebunden werden, die generiert wurden, aber gleichzeitig wollte ich keine doppelten Klassen über meine Anwendung verstreut haben.

Also hier ist meine Lösung:
ich "auf eine Schnittstelle programmiert".

Sagen wir, ich habe eine PersonDto (Dto steht für Data Transfer Object) mit Eigenschaften von FirstName, LastName, Age (die direkt auf Datenbankspalten beziehen).

Ich erstellte eine IPerson Schnittstelle und hatte meine PersonDto implementieren.

 

    [Table(Name="Persons")] 
    internal class PersonDto : IPerson 
    { 
     .... 
    } 
 

Und meine Repository Methode würde in und Abrufen von IPerson in Bezug auf die Linq2Sql Klasse gegenüber.

 

    IPerson somePerson = _repository.Get(someGuid); 
    somePerson.FirstName = "SomeName"; 
    _repository.Save(somePerson); 
 

Dieser Ansatz hat wirklich gut für mich gearbeitet. Wann immer ich das Gefühl habe, dass ich vom DTO abweichen muss, kann ich das relativ einfach tun, weil die Schnittstelle mein Objekt im Gegensatz zum DTO darstellt.

Einige allgemeine Hinweise: Erstellen Sie Ihre DTOs von Hand ... Ich weiß, es klingt verrückt, aber Sie werden feststellen, dass es wirklich gut funktioniert mit einem Top-Down, Test-driven Development-Ansatz. Ihre DTO-Objekte (linq2Sql) sind extrem hell und offen für Änderungen außerhalb des .dbml-Designers.

Halten Sie Ihre DTOs und DataContexts intern. Es gibt keinen Grund dafür, dass Ihre dto öffentlich zugänglich gemacht werden (vorausgesetzt, Sie haben öffentliche Schnittstellen für Ihre Repositories und Domain-Objekte). Dadurch wird eine logische Trennung zwischen Ihrem Domänenmodell und dem Datenzugriff erzwungen.

Legen Sie alle Datenzugriffslayer in einem separaten Projekt ab (um diese Trennung zu erzwingen).

Setzen Sie Ihre Schnittstellendeklarationen in ein separates Projekt (dadurch wird sichergestellt, dass Sie keine Zirkelverweise erhalten).

Hope this helps ...

+0

Ich liebe diese Idee ... das einzige Problem ist in MVC, die Controller können keine Schnittstellen für die Add-Methoden aufnehmen. Dies macht die Schnittstellen für MVC relativ unbrauchbar. Wie sind Sie mit diesem Problem umgegangen, weil ich das wirklich gerne machen würde? –

+0

Methode hinzufügen? kannst du es ausarbeiten, ich benutze gerade diese appraoch mit aspmvc und hatte keine probleme. – Amir

+0

"Die Controller können keine Schnittstellen für die Add-Methoden verwenden", erstellen Sie einfach ein View-Modell, das die Schnittstelle implementiert. Es kann sich im Webprojekt befinden, da es nur ein Objekt ist, das die Interaktion mit der Ansicht erleichtert. – Amir

2

Dies ist eines der besten Diskussionen über das Thema, das ich je gesehen habe:

http://blog.wekeroad.com/blog/linqtosql-momma-said-knock-you-out/

Am Ende Kopplung und Kohäsion Entscheidungen sind situationsbedingt und Sie müssen entscheiden, was für Ihre Situation am besten ist.

Wenn Ihre Anwendung LinqToSql übersteigt, wie leicht wird es sein, LinqToSql herauszuziehen und ein anderes ORM an seiner Stelle einzusetzen? Darüber müssen Sie ernsthaft nachdenken.

Im Allgemeinen minimieren Sie das Wissen, das Ihre Business-Schicht über LinqToSql hat. LinqToSql sollte vollständig von Ihrer UI-Ebene verborgen sein (Ihre Business-Schicht macht einen guten Teil dieses Schildes aus). Es ist sehr einfach, mit LinqToSql den falschen architektonischen Pfad einzuschlagen, und es kann sehr schwierig sein, nachher wieder auf den richtigen Weg zu kommen.

0

Die vom linq2sql-Designer generierten Klassen sind Teilklassen. Sie können diese also erweitern und Ihre Geschäftslogik direkt in diese Klassen einfügen. Die Idee ist, dass linq verwendet wird, um diese Entitäten persistent zu machen/zu rekonstruieren, so dass Sie die Art von Mapping vermeiden können, von der Sie sprechen.

+1

Sobald Sie die Geschäftslogik in die LinqToSql Teilklassen beginnen Einbettung, ist es sehr schwer, sie später zu entkoppeln. Wenn Sie keine Business-Schicht möchten/brauchen, ist das in Ordnung, aber das ist nicht immer der richtige Weg. Außerdem ist es schwierig, LinqToSql zu einem späteren Zeitpunkt durch ein anderes ORM mit einem anderen Feature-Set zu ersetzen (was möglicherweise erforderlich ist). –

+0

Der Punkt ist, Ihre linqToSql Entitäten sind Teil der 'Business-Schicht' und das Repository wird verwendet, um sie in der Datenbank abzurufen/persistieren. Ja, es gibt eine Kopplung mit dem linq Designer, aber das ist ein anderes Problem. – Lee

+0

@Lee: Nein, Sie sollten linq2sql nicht für Ihre Business-Schicht verwenden. Es ist ein WUNDERBARER objektrelationaler Mapper, aber ich möchte Sie ermutigen, nicht in diese Falle zu geraten. Ihre Datenbank ist eine Normalisierung von Daten, Ihre Business-Schicht ist eine Normalisierung von Verhaltensweisen. – Amir

3

Ich hatte tatsächlich eine ähnliche Frage zu diesem Thema, obwohl meine Absicht etwas anders war. Die Empfehlung war, die Linq2SQL-Klassen als Domänenobjekte zu verwenden und partielle Klassen zu nutzen, wie andere bereits erwähnt haben. Mein Hauptanliegen betraf die Form dieser Objekte (dh Eigenschaftsnamen) und die Zugänglichkeit von Klassenmitgliedern (dh zum Beispiel private vs. protected).

Die Form der Objekte und sogar die Zugänglichkeit können mithilfe von t4-Vorlagen angegangen werden, wo Damien Guard eine T4-Vorlage zusammengestellt hat, mit der Sie die Form der Klassen steuern können, die Linq2Sql für Sie generieren würde. Dies kann hier T4 template for Linq2SQL gesehen werden.

Dies ist der Ansatz, den ich untersuchen werde und sehen, ob es meine Bedenken angeht. Wenn Ihre Service-Schicht Schnittstellen zu Methodenargumenten akzeptieren kann, können Sie außerdem steuern, auf welche Ebene die Service-Schicht über Schnittstellen-Wrapper rund um Ihre Linq2SQL-DTOs zugreifen kann.

Hoffe, das hilft.