版本库模式实施经验
问题描述:
我正准备开始一个新的asp.net web项目,并且我要去LINQ到SQL。我已经完成了一些工作,使用我在Mike Hadlow中发现的一些信息来获取数据层设置,这些信息使用Interface和泛型为数据库中的每个表创建一个Repository。起初我认为这是一个有趣的方法。然而,现在我认为创建一个基本Repository类并从它继承来为我需要访问的表创建一个TableNameRepository类会更有意义。版本库模式实施经验
哪种方法将允许我以清洁可测试的方式添加特定于表格的功能?这是我的Repository实现供参考。
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这样有用的东西。
答
您不应该为每个表创建存储库。
相反,您应该为您的域模型中存在的每个“实体根”(或聚合根)创建一个存储库。您可以了解更多的模式,在这里看到一个工作例子:
你是不是问一个具体问题。 – ddaa 2008-09-19 14:24:30