1

Ich habe fast fertig implementiert meine Repository-Muster mit einer IRepository<T> Schnittstelle, eine NewsRepository Klasse und eine News Einheit. Das Problem, auf das ich stieß, war der Versuch, gängige Methoden zu einer Basis-Repository-Klasse zu abstrahieren.Wie Implementieren Repository-Muster mit Schnittstelle, Basis und Beton

Ich konnte keinen Weg finden, die Methode Get in NewsRepository zu abstrahieren, da sie einen bestimmten Linq-Ausdruck enthält.

Meine Fragen sind:

1) Wie kann ich auf eine Basisklasse abstrakt die public T Get(int id) Methode bitte? Die einzige Möglichkeit, die ich bisher gemacht habe, besteht darin, Expression<Func<T,bool>> anstelle eines int zu übergeben, aber dann wird das allgemeine Verhalten nicht wirklich abstrahiert, da jede Unterklasse immer noch einen Ausdruck geben muss, der in jedem Fall fast identisch ist dh n => n.id == id.

2) Wie gebe ich in die Basisklasse auf die Update-Methode die Unterklasse GetViolations und Kartenmethoden bitte? Ich stelle mir vor, die Lösung ist möglicherweise durch die Verwendung von Delegaten, aber ich konnte nicht die Syntax kompilieren

Dies ist eine vereinfachte Menge des Codes - in der Praxis habe ich eine Save-Methode, die Update und fügt statt nur das Update hier gezeigt.

public interface IRepository<T> 
{ 
    T Get(int id); 
    void Update(T item); 
} 

public class NewsRepository : IRepository<News> 
{ 
    private Table<News> _newsTable; 
    public NewsRepository(string connectionString) 
    { 
     _newsTable = new DataContext(connectionString).GetTable<News>(); 
    } 

    public News Get(int id) 
    { 
     return _newsTable.SingleOrDefault(n => n.NewsId == id); 
    } 

    public void Update(News item) 
    { 
     var errors = item.GetRuleViolations(); 
     if (errors.Count > 0) 
      throw new RuleException(errors); 

     News dbNews = _newsTable.SingleOrDefault(n => n.NewsId == item.NewsId); 
     map(dbNews, item); 

     _newsTable.Context.SubmitChanges(); 
    } 

    private void map(News dbNews, News news) 
    { 
     dbNews.Title = news.Title; 
     dbNews.Article = news.Article; 
    } 
} 

public class Repository<T> where T : class 
{ 
    protected Table<T> _table; 

    public Repository(Table<T> t) 
    { 
     _table = t; 
    } 

    //How do i do this??! - This doesn't compile due to T no having a NewsId 
    public T Get(int id) 
    { 
    return _table.SingleOrDefault(n => n.NewsId == id); 
    } 

    //This seems to be a solution, but it's not really abstracting common behaviour as each 
    //sub-class will still need to pass in the same linq expression... 
    public T Get(Expression<Func<T,bool>> ex) 
    { 
     return _table.SingleOrDefault(ex); 
    } 

    public void Update(T item) 
    { 
     //How is it possible to pass in the GetRuleViolations and map functions to this method? 
     var errors = item.GetRuleViolations(); 
     if (errors.Count > 0) 
      throw new RuleException(errors); 

     T dbNews = _table.SingleOrDefault(n => n.NewsId == item.NewsId); 
     map(dbNews, item); 

     _table.Context.SubmitChanges(); 
    } 
} 

Antwort

1
  1. Es hilft wirklich eine layer supertype for entities zu haben. Sie teilen eine Id-Eigenschaft. Sie müssen sich nicht mit einem Ausdruck beschäftigen, um die ID-Funktion darzustellen, Sie werden nur wissen, was es ist.

  2. Die template method pattern. In diesem Muster führt Ihr Basis-Update alle Arbeitsschritte aus, die Hilfsmethoden der Reihe nach aufrufen, und Ihre abgeleiteten Klassen implementieren diese geschützten abstrakten Hilfsmethoden.

2
  1. L2S unterstützt weder Schicht übergeordneten Typen noch über Schnittstellenelemente in Abfragen, die recht schwierig wiederzuverwenden macht. Eine Möglichkeit besteht darin, dynamisch eine Ausdrucksstruktur zu erstellen. Es ist ein bisschen chaotisch, aber wenn Sie es auf Ihr Basisklassen-Repository isolieren, ist es nicht so schlimm. Hier

ist ein Beispiel:

public interface IEntity 
{ 
    int Id { get; } 
} 

public partial class News : IEntity 
{ 
} 

public class Repository<T> where T : class, IEntity 
{ 

    private readonly DataContext _db; 

    public Repository(DataContext db) 
    { 
     _db = db; 
    } 

    public T Get(int id) 
    { 
     Expression<Func<T, bool>> hasId = HasId(id); 
     return _db.GetTable<T>().Single(hasId); 
    } 

    // entity => entity.Id == id; 
    private Expression<Func<T, bool>> HasId(int id) 
    { 
     ParameterExpression entityParameter = Expression.Parameter(typeof (T), "entity"); 
     return Expression.Lambda<Func<T, bool>>(
      Expression.Equal(
       Expression.Property(entityParameter, "Id"), 
       Expression.Constant(id) 
       ), 
      new[] {entityParameter} 
      ); 
    } 
} 

Siehe auch http://msdn.microsoft.com/en-us/library/bb397951.aspx

Verwandte Themen