Ich arbeite an der Integration einiger gemeinsamer Repository-Infrastruktur in einige Anwendungen, die EF, L2SQL und WCF Data Services umschließen (obwohl die zugrunde liegenden Data Access-Implementierungen beliebig sein sollten). Ich habe etwas darüber gelesen, aber ich finde kein Beispiel, das wirklich befriedigt.Generic Repository
Ich begann mit:
public interface IRepository : IDisposable
{
IQueryable<T> Query<T>();
void Attach(object entity);
void ForDeletion(object entity);
void SaveChanges();
}
Aber Ich mag die Idee eines Endlagers mit schmalen Domain Verträge (http://codebetter.com/blogs/gregyoung/archive/2009/01/16/ddd-the-generic-repository.aspx). Das oben Genannte verlässt den Benutzer, um alle Entitätstypen zu kennen, die vom Repository unterstützt werden.
Ich werde nicht sagen, dass es nicht in Frage kommt, aber ich wäre sehr schwer, überzeugt zu sein, dass IQueryables selbst nicht Teil des Repository-Vertrags sein sollte. Ich bin kein Fan von Kesselplatten-Code und ich glaube fest, dass je mehr Sie haben, desto mehr Wartung schwarze Löcher, die Sie einführen. Also, was ich sage ist, dass es sehr schwer sein würde, mir das alles zu überzeugen, die wie folgt aussieht:
Public IEnumerable<Customer> GetCustomersWithFirstNameOf(string _Name) {
internalGenericRepository.FetchByQueryObject(new CustomerFirstNameOfQuery(_Name)); //could be hql or whatever
}
ist alles andere als ein völlig abgründigen Idee. Wie wäre es, wenn Sie nach dem Nachnamen und Nachnamen suchen möchten. Oder Vorname oder Nachname ... etc. Sie haben am Ende ein Repository mit mehr als 1000 Operationen, von denen die Hälfte dieselbe Logik wiederholt. Hinweis: Ich bin nicht der Aufruf Code sollte für die Anwendung alle Filterung und so verantwortlich sein, sondern vielmehr, dass eine ergänzende Spezifikation Quelle macht Sinn für mich:
public static class CustomerSpecifications
{
public IQueryable<Customer> WithActiveSubscriptions(this IQueryable<Customer> customers, DateTime? start, DateTime? end)
{
// expression manipulation
return customers;
}
}
// bind some data source
repository.GetQueryable().WithActiveSubscriptions();
Ok, so vorwärts bewegt, ich denke, die Domain-Modell explizite Repositorys klingt wie eine gute Idee in folgendem Format:
public interface IRepository : IDisposable
{
void SaveChanges();
}
public interface IRepository<T>: IRepository
{
IQueryable<T> GetQueryable();
void Attach(T entity);
void ForDeletion(T entity);
}
dann
public class CustomerRepository:IRepository<Customer>
{
private ObjectContext _context;
// trivial implementation
}
aber mein Problem dabei ist, dass es erlaubt mir nur delet e Kunden. Was ist mit dem Fall, in dem ich die Adresse eines Kunden löschen möchte? Das heißt, ich verwende das Repository, um eine Customer-Entität abzufragen, möchte aber dann myCustomer.CustomerAddresses [0] löschen. Ich muss ein zweites Repository erstellen, um die gewünschte Adresse anzuhängen und zu löschen.
Ich glaube, ich meine CustomerRepository sein könnte:
public class CustomerRepository:IRepository<Customer>, IRepository<CustomerAddress>
{
private ObjectContext _context;
// trivial implementation
}
, die mir das Repository wiederverwenden lassen würde CustomerAddresses zu löschen, aber ich bin nicht sicher, wie ich über Vererbungs fühlen IRepository<T>
für jeden Teil des Graphen I löschen wollen für ...
Wer hat irgendwelche Vorschläge für eine bessere Umsetzung?
Sie haben also ein GenericRepository pro Aggregat root ... wie in keinem GenericRepository für CustomerAddress? –
Jeff
@ JeffN825. Richtig. Versuchen Sie, nicht in die Denkweise von "Ich brauche ein Repository pro Entität" einzudringen. Denken Sie darüber nach, * wie * Ihre Entitäten abgerufen werden. Können Sie jemals eine Kundenadresse abrufen, ohne einen Kunden zu haben? Wahrscheinlich nicht - daher sollten Sie kein CustomerAddress-Repository haben. – RPM1984
@ JeffN825 - und auch, erinnere dich 'GenericRepository' verwendet Generika, so dass es nur 1 Datei gibt. Es wird injiziert (über DI), wenn der Code eine bestimmte Schnittstelle anfordert. In Ihrem Beispiel geben Sie 'GenericRepository ' '' CustomerRepository' (das 'GenericRepository ' erbt) –
RPM1984