2010-12-16 10 views
3

Ich möchte den Repository-Ansatz, der in DDD mit Linq-2-Sql in meiner Portal-App weit verbreitet ist, nachahmen. Bisher habe ich dies:Unit of Work-Muster vs. Transaktionsumfang für Linq-To-Sql?

 public class LinqToSqlDal<DC,T>: IDisposable, IRepository<T> 
     where T: LinqEntity, new(), 
     where DC: DataContext, new() 
    { 

       private DC unitOfWork = null; 

       public LinqToSqlDal(string connectionString) 
       { 
        this.unitOfWork = Activator.CreateInstance(typeof(DC), connectionString) as DC; 
       } 

       public LinqToSqlDal(string connectionString, DataLoadOptions loadOptions): this(connectionString) 
       { 
        this.unitOfWork.LoadOptions = loadOptions; 
       } 

       public virtual void SubmitChanges() { 
       this.unitOfWork.SubmitChanges(); 
       } 

       public virtual List<T> Get(Expression<Func<T,bool>> query) 
       { 
        return this.unitOfWork.GetTable<T>().Where(query); 
       } 

       public virtual void Delete(Expression<Funct<T, bool>> query) 
       { 
        this.unitOfWork.GetTable<T>().DeleteAllOnSubmit(this.unitOfWork.GetTable<T>().Where(query)); 
       } 

       public virtual T GetByID<T>(Expression<Funct<T, bool>> query) 
       { 
        return this.unitOfWork.GetTable<T>().Where(query).SingleOrDefault(); 
       } 

       public virtual object Add(T entity, string IDPropertyName) 
       { 
       this.unitOfWork.GetTable<T>().InsertOnSubmit(entity); 
       this.SubmitChanges(); 

       var ID = (string.IsNullOrEmpty(IDPropertyName)) ? null : 
        entity.GetType().GetProperty(IDPropertyName).GetValue(entity, null); 

        return ID; 
       } 

       public virtual void SubmitChanges() 
       { 
        this.unitOfWork.SubmitChanges(); 
       } 

       public void Dispose() 
       { 
       this.unitOfWork.Dispose(); 
       } 


    } 

So jetzt habe ich dies mit jedem Entity verwenden können und Datacontext, die Einheit gehört. Meine Frage ist - würde ein TransactionScope innerhalb dieses kleinen Repository-Vorteils weitergeben oder instanziieren? Bisher habe ich nur einen DataContext, kann aber mehrere vorwärts haben, was kann mit dem aktuellen Design getan werden, um Transaktionen über mehrere Datenkontexte hinweg sicherzustellen?

Ist dies ein guter Ansatz, um den Kontext mit Generika zu verpacken und die Kunden davon zu befreien?

Antwort

3

Ich würde definitiv eine Art zentralisierte, aber extern gesteuerte Transaktionssteuerung erstellen. Persönlich bevorzuge ich UnitOfWork, weil Sie es als eine Zusammenfassung entwerfen können, die nur an das Repository-Modell und nicht an irgendwelche implementierungsspezifischen Details gebunden ist.

Derzeit ist Ihre Arbeitseinheit implementierungsspezifisch. Ihre Entwickler wissen, dass das Objekt namens unitOfWork eigentlich ein DataContext für Linq2SQL ist. Mit diesem Wissen können sie das Repository vollständig umgehen und eine UnitOfWork verwenden, um ihre DB-Aufrufe durchzuführen. Es wäre eine schlechte Idee für sie, dies zu tun, aber die Tatsache, dass sie dies tun können, lässt auf die Notwendigkeit schließen, die spezifischen Details hinter einem besseren Abstract besser einzukapseln.

Ich würde UnitOfWork eine Tokenklasse machen; Das Token ist lediglich ein abstrakter Platzhalter, der sich auf die atomare Menge von Operationen bezieht. Hinter den Kulissen können Sie UnitsOfWork verwenden, um eine Sammlung von DataContexts zu markieren, und den Kontext für ein bestimmtes UnitOfWork verwenden, wenn dieses Token dem Repository von einer aufrufenden Methode präsentiert wird (es würde als Parameter übergeben). Wenn der UnitOfWork durch externen Code verworfen wird, muss der DataContext entsorgt werden. Wenn Sie Ihr Repository so entwerfen, bedeutet dies, dass für die Verwendung von Code keine Kenntnis der Implementierungsdetails erforderlich ist. Wenn Sie später entscheiden, dass Linq2SQL Ihren Anforderungen nicht entspricht und Sie zu NHibernate wechseln möchten, enden die Änderungen an der Repository-Grenze. Ihr verbrauchender Code gibt keine fliegende Drehung, wenn sich UnitOfWork auf einen DataContext oder eine ISession bezieht.

+1

Toller Kommentar, könnten Sie einen Pseudo-Code zum Starten der Abstraktion der spezifischen Implementierung des DataContext bereitstellen, damit er später in eine andere Implementierung geändert werden kann? – dexter