Domanda

Mi sto preparando per iniziare un nuovo progetto web asp.net e vado a LINQ-to-SQL. Ho lavorato un po 'per ottenere la configurazione del mio livello dati utilizzando alcune informazioni che ho trovato da Mike Hadlow che utilizza un'interfaccia e generici per creare un repository per ogni tabella nel database. All'inizio ho pensato che fosse un approccio interessante. Tuttavia, ora penso che potrebbe avere più senso creare una classe Repository di base ed ereditarla per creare una classe TableNameRepository per le tabelle a cui devo accedere.

Quale approccio mi consentirà di aggiungere funzionalità specifiche di una tabella in modo pulito e verificabile? Ecco l'implementazione del mio repository per riferimento.

public class Repository<T> : IRepository<T> where T : class, new()
{
    protected IDataConnection _dcnf;

    public Repository()
    {
        _dcnf = new DataConnectionFactory() as IDataConnection;
    }

    // Constructor injection for dependency on DataContext 
    // to actually connect to a database
    public Repository(IDataConnection dc)
    {
        _dcnf = dc;
    }

    /// <summary>
    /// Return all instances of type T.
    /// </summary>
    /// <returns>IEnumerable<T></returns>
    public virtual IEnumerable<T> GetAll()
    {
        return GetTable;
    }

    public virtual T GetById(int id)
    {
        var itemParam = Expression.Parameter(typeof(T), "item");
        var whereExp = Expression.Lambda<Func<T, bool>>
            (
                Expression.Equal(
                    Expression.Property(itemParam, PrimaryKeyName),
                    Expression.Constant(id)
                ), new ParameterExpression[] { itemParam }
            );
        return _dcnf.Context.GetTable<T>().Where(whereExp).Single();
    }

    /// <summary>
    /// Return all instances of type T that match the expression exp.
    /// </summary>
    /// <param name="exp"></param>
    /// <returns>IEnumerable<T></returns>
    public virtual IEnumerable<T> FindByExp(Func<T, bool> exp)
    {
        return GetTable.Where<T>(exp);
    }

    /// <summary>See IRepository.</summary>
    /// <param name="exp"></param><returns></returns>
    public virtual T Single(Func<T, bool> exp)
    {
        return GetTable.Single(exp);
    }

    /// <summary>See IRepository.</summary>
    /// <param name="entity"></param>
    public virtual void MarkForDeletion(T entity)
    {
        _dcnf.Context.GetTable<T>().DeleteOnSubmit(entity);
    }

    /// <summary>
    /// Create a new instance of type T.
    /// </summary>
    /// <returns>T</returns>
    public virtual T Create()
    {
        //T entity = Activator.CreateInstance<T>();
        T entity = new T();
        GetTable.InsertOnSubmit(entity);
        return entity;
    }

    /// <summary>See IRepository.</summary>
    public virtual void SaveAll()
    {
        _dcnf.SaveAll();
    }

    #region Properties
    private string PrimaryKeyName
    {
        get { return TableMetadata.RowType.IdentityMembers[0].Name; }
    }

    private System.Data.Linq.Table<T> GetTable
    {
        get { return _dcnf.Context.GetTable<T>(); }
    }

    private System.Data.Linq.Mapping.MetaTable TableMetadata
    {
        get { return _dcnf.Context.Mapping.GetTable(typeof(T)); }
    }

    private System.Data.Linq.Mapping.MetaType ClassMetadata
    {
        get { return _dcnf.Context.Mapping.GetMetaType(typeof(T)); }
    }
    #endregion
}
È stato utile?

Soluzione

Sarei tentato di suggerire che se usi tipi di calcestruzzo o meno non dovrebbe importare, come se usassi l'iniezione di dipendenza (castello?) per creare i repository (in modo da poterli avvolgere con cache diverse ecc.) codebase non sarà il più saggio a prescindere dal modo in cui l'hai fatto.

Quindi chiedi semplicemente al tuo DI un repository. Per esempio. per il castello:

public class Home {
  public static IRepository<T> For<T> {
    get {
      return Container.Resolve<IRepository<T>>();
    }
  }
}

Personalmente, non avrei toccato il fondo dei tipi fino a quando non ne avessi bisogno.

Suppongo che l'altra metà della tua domanda sia se puoi facilmente fornire un'implementazione in memoria di IRepository a scopo di test e memorizzazione nella cache. Per questo farei attenzione perché linq-to-object può essere lento e potresti trovare qualcosa come http: // www .codeplex.com / i4o utile.

Altri suggerimenti

Non è necessario creare un repository per ogni tabella.
Invece, dovresti creare un repository per ogni "radice dell'entità" (o radice aggregata) che esiste nel tuo modello di dominio. Puoi saperne di più sul modello e vedere un esempio funzionante qui:

http://deviq.com/repository-pattern/

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top