存储库模式实施经验
时间:2020-03-06 14:26:09 来源:igfitidea点击:
我准备开始一个新的asp.net Web项目,并且要使用LINQ-to-SQL。我已经完成了一些工作,使用Mike Hadlow发现的一些信息来设置数据层,该信息使用接口和泛型为数据库中的每个表创建一个存储库。我一开始认为这是一种有趣的方法。但是,现在我认为创建一个基本的Repository类并从中继承来为我需要访问的表创建TableNameRepository类可能更有意义。
哪种方法可以让我以干净的可测试方式添加特定于表的功能?这是我的存储库实现,以供参考。
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 }
解决方案
我很想建议我们是否使用具体类型都没关系,就像我们使用依赖项注入(城堡?)来创建存储库(以便我们可以将它们包装在不同的缓存中)一样,那么代码库将是无论我们采用哪种方式,都没有一个明智的选择。
然后,向DI索要一个存储库。例如。对于城堡:
public class Home { public static IRepository<T> For<T> { get { return Container.Resolve<IRepository<T>>(); } } }
就个人而言,除非我们有需要,否则我不会对这些类型进行深入研究。
我猜我们问题的另一半是我们是否可以轻松地提供IRepository的内存中实现以进行测试和缓存。为此,我会注意linq-to-objects可能很慢,并且我们可能会发现像http://www.codeplex.com/i4o之类的有用内容。