1

Ich habe N-Layer-Lösung in. Net mit PetaPoco als microORM. Ich bekomme die Entities aus dem Template-Generator von PetaPoco. Diese Entitäten T stammen von der Basisklasse Record<T>. Dann erweitere ich sie um weitere Datenzugriffseinrichtungen und benutzerdefinierte Save() und Delete() Methoden, die die Record<T> Standardmethoden überschreiben..net generisches Repository-Problem mit petapoco

Im Folgenden ist die overrided Delete Methode aus der Einheit (die Methode, die ich anrufen mag)

public partial class Document : Record<Document> 
{ 
    public new int Delete() 
    { 
     int rowsAffected; 
     using (var uow = DB.GetInstance().GetTransaction()) 
     { 
      rowsAffected = base.Delete(); 
      LogSystem("Deleting", "Deleting a document", 0, 0, GUID); 
      uow.Complete(); 
     } 
     return rowsAffected; 
    } 
} 

Dann, wenn ich die generische Repository erstelle die Methoden sind von der Basisklasse immer genannt Record<T> und nicht meine Gewohnheit einer von den Entitäten. Wenn ich eine entityRepository.Delete()-Methode aufrufen, sollte die Delete()-Methode von meiner Entität aufgerufen werden und nicht die aus der Standardklasse Record<T>.

Die generische Repository-Klasse ist als follwos:

public abstract class GenericRepository<T> : IGenericRepository<T> where T : Record<T>, new() 
{ 
    public void Delete(T entity) 
    { 
     entity.Delete(); 
    } 
} 
+0

mit DapperExtensions meine Antwort finden. Auch wenn Sie PetaPoco verwenden, sollten andere Dinge ähnlich sein. https://stackoverflow.com/a/45460483/5779732 –

+0

Hey Mann danke für die Antwort, ich habe bereits in diese Frage schauen, aber es beantwortet nicht, wie ich meine überlagerten Methoden der Entitäten und nicht die generischen aus der Basisklasse. Außerdem verstehe ich nicht, wie man das UoW-Muster integriert, wie Sie sehen, ich benutze es irgendwie, aber als die PetaPoco-Transaktion, von der ich nicht weiß, ob sie wie oben verwendet werden sollte. –

+0

Auch ich bin in jedem Design-Eingang suchen –

Antwort

0

Die Ursache für dieses Problem ist, dass Sie in Ihrer GenericRepository T als "etwas von Record ableiten" angeben. Also, ideal entity.Delete() Aufruf, wird dieser Aufruf dieser Basismethode verknüpft werden, da dies nur einmal für alle möglichen Fälle von T. erfolgt

Wenn Sie Zugriff auf die Klasse Record<T> haben, sondern nur die Delete() Methode virtuellen machen und sie überschreiben in Document.

Wenn nicht, versuchen Sie so etwas wie dies mit:

public class ExtendedRecord<T>: Record<T> 
{ 
    public virtual new int Delete() 
    { 
    base.Delete(); 
    } 
} 

public partial class Document : ExtendedRecord<Document> 
{ 
    public override int Delete() 
    { 
    // ... 
    } 
} 

public abstract class GenericRepository<T> : IGenericRepository<T> 
    where T : ExtendedRecord<T>, new() 
{ 
    // ... 
} 
+0

Dies ist "Lösung 3:" wie ich in meiner Antwort vorgeschlagen habe. –

+0

Schließlich habe ich beschlossen, die Methoden aus der Record Klasse nicht zu überschreiben. Stattdessen verschiebe ich stattdessen die Logging-Logik in das Repository. Dank an alle. –

0

Geständnis: Ich habe keine Kenntnis von PetaPoco und seine Vorlage Generator.

Das Problem hängt eher mit OO (speziell Vererbung) als mit PetaPoco IMHO zusammen. Wenn das generische Repository mit Record<T> erstellt wird, das auch eine Basisklasse für jede Entität ist, dann ist das, was passiert, wie erwartet. Sie müssen die Vererbung Ihrer Klassen genau untersuchen.

Möglicherweise müssen Sie einige Änderungen an der unten vorgeschlagenen Lösung vornehmen, um mit der ORM-Funktionalität übereinzustimmen.

Lösung 1:

public interface IEntityBase{..... 

Fügen Sie die notwendigen Elemente wie Delete Methode in der Schnittstelle:

eine Basisklasse oder Schnittstelle so etwas wie unten Deklarieren neu.

Dann leiten jede Entität von dieser Schnittstelle auch:

public partial class Document : Record<Document>, IEntityBase 

Dann eine generische Repository mit dieser Schnittstelle wie unten statt Record<T>etwas schaffen:

public abstract class GenericRepository<T> : IGenericRepository<T> where T : IEntityBase 

Auf diese Weise, Sie erreichen Ihr Ziel, ohne viel von Ihrem bestehenden Code zu ändern.

Lösung 2:

Eine weitere schmutzig Lösung ist, die Record<T> auf seine eigentliche Instanz zu werfen.

public void Delete(T entity) 
{ 
    if(typeof(T) == typeof(Document)) 
     Document myEntity = (Document)entity; 
    myEntity.Delete(); 
} 

Casting in jeder Methode ist definitiv schlechte Idee. Suchen Sie nach einem besseren zentralen Speicherort in Ihrem Code. Ich wollte dir nur den Weg zeigen.

Lösung 3:

Anderer Gedanke ist Delete Methode in Record<T> ein virtual Verfahren zu machen. Aber ich bin mir nicht sicher, wie dein ORM funktioniert oder ob dein ORM dies erlaubt, also werde ich das nicht kommentieren.