C# 存储库模式实施经验
我正准备开始一个新的asp.net web项目,我将使用LINQ to SQL。我已经做了一点工作,使用我找到的一些信息来设置数据层,这些信息使用一个接口和泛型为数据库中的每个表创建一个存储库。起初我认为这是一个有趣的方法。但是,现在我认为创建一个基本存储库类并从中继承来为我需要访问的表创建一个TableNameRepository类可能更有意义 哪种方法将允许我以干净的可测试的方式添加特定于表的功能?以下是我的存储库实现,以供参考C# 存储库模式实施经验,c#,design-patterns,linq-to-sql,repository-pattern,C#,Design Patterns,Linq To Sql,Repository Pattern,我正准备开始一个新的asp.net web项目,我将使用LINQ to SQL。我已经做了一点工作,使用我找到的一些信息来设置数据层,这些信息使用一个接口和泛型为数据库中的每个表创建一个存储库。起初我认为这是一个有趣的方法。但是,现在我认为创建一个基本存储库类并从中继承来为我需要访问的表创建一个TableNameRepository类可能更有意义 哪种方法将允许我以干净的可测试的方式添加特定于表的功能?以下是我的存储库实现,以供参考 public class Repository<T>
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
}
公共类存储库:IRepository,其中T:class,new()
{
受保护的IDataConnection\u dcnf;
公共存储库()
{
_dcnf=新的DataConnectionFactory()作为IDataConnection;
}
//依赖于DataContext的构造函数注入
//实际连接到数据库的步骤
公共存储库(IDataConnection dc)
{
_dcnf=dc;
}
///
///返回T类型的所有实例。
///
///数不清
公共虚拟IEnumerable GetAll()
{
返回GetTable;
}
公共虚拟T GetById(int id)
{
var itemParam=表达式参数(typeof(T),“item”);
var whereExp=Expression.Lambda
(
表达式。相等(
Expression.Property(itemParam,PrimaryKeyName),
表达式.常量(id)
),新参数表达式[]{itemParam}
);
返回_dcnf.Context.GetTable().Where(whereExp.Single();
}
///
///返回与表达式exp匹配的T类型的所有实例。
///
///
///数不清
公共虚拟IEnumerable FindByExp(Func exp)
{
返回GetTable.Where(exp);
}
///见我的推测。
///
公共虚拟T单(功能扩展)
{
返回GetTable.Single(exp);
}
///见我的推测。
///
公共虚空标记删除(T实体)
{
_dcnf.Context.GetTable().DeleteOnSubmit(实体);
}
///
///创建类型为T的新实例。
///
///T
公共虚拟T创建()
{
//T entity=Activator.CreateInstance();
T实体=新的T();
GetTable.InsertOnSubmit(实体);
返回实体;
}
///见我的推测。
公共虚拟void SaveAll()
{
_dcnf.SaveAll();
}
#区域属性
私有字符串PrimaryKeyName
{
获取{return TableMetadata.RowType.IdentityMembers[0].Name;}
}
private System.Data.Linq.Table可获取
{
获取{return}dcnf.Context.GetTable();}
}
private System.Data.Linq.Mapping.MetaTable表元数据
{
获取{return}dcnf.Context.Mapping.GetTable(typeof(T));}
}
private System.Data.Linq.Mapping.MetaType类元数据
{
获取{return}dcnf.Context.Mapping.GetMetaType(typeof(T));}
}
#端区
}
我想建议,您是否使用具体类型并不重要,就像您使用依赖项注入(castle?)来创建存储库一样(这样您就可以用不同的缓存等包装它们),那么无论您采用何种方式,您的代码库都不会变得更明智
然后向您的DI请求一个存储库。例如,对于castle:
public class Home {
public static IRepository<T> For<T> {
get {
return Container.Resolve<IRepository<T>>();
}
}
}
公共类主页{
公共静态存储{
得到{
返回Container.Resolve();
}
}
}
就我个人而言,在你找到需要之前,我不会把这些类型弄到底
我想您的另一半问题是,您是否可以轻松地为测试和缓存目的提供IRepository的内存实现。对于这一点,我会注意linq to对象可能会很慢,您可能会发现一些有用的东西。我会建议您是否使用具体类型应该无关紧要,就像您使用依赖项注入(castle?)来创建存储库一样(这样您就可以用不同的缓存等包装它们)那么不管你用什么方法,你的代码库都不会变得更聪明 然后向您的DI请求一个存储库。例如,对于castle:
public class Home {
public static IRepository<T> For<T> {
get {
return Container.Resolve<IRepository<T>>();
}
}
}
公共类主页{
公共静态存储{
得到{
返回Container.Resolve();
}
}
}
就我个人而言,在你找到需要之前,我不会把这些类型弄到底
我想您的另一半问题是,您是否可以轻松地为测试和缓存目的提供IRepository的内存实现。为此,我要注意linq to对象可能会很慢,您可能会发现类似的东西很有用。您不应该为每个表创建存储库。
相反,您应该为域模型中存在的每个“实体根”(或聚合根)创建一个存储库。您可以了解有关该模式的更多信息,并在此处查看一个工作示例:
您不应该为每个表创建存储库。
相反,您应该为域模型中存在的每个“实体根”(或聚合根)创建一个存储库。您可以了解有关该模式的更多信息,并在此处查看一个工作示例:
您没有提出具体问题。请把问题说清楚,否则它将以“非真实问题”结束。您没有提出具体问题。请把问题说清楚,否则它将以“非真实问题”结束