[英]Design pattern for Data Access Layer
您可能会觉得这是家庭作业,对不起。 我已经搜索过,但是找不到正确的答案。
所以我的问题是:
我有几个类,每个类都有一个保存方法。 因此,我为数据库处理创建了一个单独的类。
namespace HospitalMgt.Data
{
public static class DBConnection
{
public static string constr = "Data Source=ABD;Initial Catalog=HospitalMgt;User Id=sa;Password=123";
public static SqlConnection con;
// public static SqlCommand com;
public static SqlConnection OpenConnection()
{
con= new SqlConnection(constr);
con.Open();
return con;
}
}
}
但是,我认为用DBConnection类实现所有类并不适合。
我的问题 :
我使用Factory方法发现了一些有关DA层的文章,但是据我所知,这种模式不适合我的情况。
通常,如果我不能使用任何现有框架,那么我会同时使用存储库和活动模式。
为简单起见,您只能使用存储库模式。 我通常这样定义:
public interface IEntity<T> { }
// Define a generic repository interface
public interface IRepository<TKey, TEntity>
where TEntity : IEntity<TKey>
{
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
IEntity<TKey> Get(TKey key);
IEnumerable<TEntity> GetRange(IEnumerable<TKey> keys);
IEnumerable<TEntity> GetAll();
// ..., Update, Delete methods
}
// Create an abstract class that will encapsulate the generic code
public abstract class Repository<TKey, TEntity> : IRepository<TKey, TEntity>
where TEntity : IEntity<TKey>
{
protected Repository(/*parameter you may need to implement the generic methods, like a ConnectionFactory, table name, entity type for casts, etc */) { }
public override void Insert(IEntity<TKey> entity)
{
// do the insert, treat exceptions accordingly and encapsulate them in your own and more concise Exceptions, etc
}
// ...
}
// Create the entities classes, one for each table, that will represent a row of that table
public class Car : IEntity<string> {/* Properties */}
// Create a specific repository for each table
// If the table have a composed key, just create a class representing it
public class CarRepository : Repository<string, Car>
{
public CarRepository() {/* pass the base parameters */}
// offer here your specific operations to this table entity
public IEnumerable<Car> GetByOwner(PersonKey ownerKey)
{
// do stuff
}
}
显然,在执行自己的实现时,必须考虑到线程安全性,尤其是在不同的实体存储库之间,要善加使用事务。
// simple example
ITransaction t = TransactionFactory.GetNewTransaction();
t.begin();
try{
// create person entity
personRepository.Add(person, t);
// create cars assigned to person
carRepository.AddRange(cars, t);
t.commit();
}catch(Exception){
t.rollback();
}
只需确保您确实要创建自己的DAL,因为它可能会变得极其复杂,特别是尝试开发最通用的解决方案。
我建议使用ORM,Entity Framework或NHibernate会很好。 然后,您不必担心数据库上下文或创建SQL语句。
首先,我想向您推荐Jeremy Miller的文章Data Persistence的设计模式 。
有一些数据访问层模式:
我建议您对所有这些常用操作使用RepositoryBase。 如果您决定使用ORM进行数据访问,最好考虑基于通用类型存储库的存储库实现。
这是一篇很好的文章:
http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/
它太旧了,但是只是围绕这个问题而已,无法抗拒发表我的想法。
我发现带有UnitOfWork的 仓库以及一些下降的ORM是很好的方法。 这样可以最大程度地减少大多数问题。
可以将以上链接中提到的UoW注入存储库中。 这增加了使用的灵活性。 同样,所有DB Communication代码都集中在一个地方。 该示例不是完整的,而是一个启动点。
上面链接中提到的存储库模式实际上是一个通用基类。 您可以为每个派生自其的具体存储库创建新类。
通用存储库被视为反模式; 互联网上有很多文章对此进行了解释。
为什么通用存储库是反模式的?
GetById()
,标识符类型可能不同。 我建议你阅读这些( 1 , 2 , 3 , 4 , 5 )的文章解释了为什么通用存储库是一个ANIT模式。
解:
无论如何,请勿将通用存储库暴露给调用代码。 另外,请勿从具体存储库中公开IQueryable
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.