你可能觉得这是作业,因为我很抱歉。我搜索过但找不到合适的答案。
所以我的问题是:
我有几个类,每个类都有一个保存方法。所以我为数据库处理创建了一个单独的类。
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图层的文章,但据我所知,这种模式并不适合我的情况。
答案 0 :(得分:13)
通常,如果我不能使用任何现有框架,我同时使用Repository和Active模式。
为简单起见,您只能使用Repository模式。我通常这样定义:
// Define a generic repository interface
public interface IRepository<Key, E> where E:IEntity<Key>>{
void Add(E entity);
void AddRange(IEnumerable<E> entities);
IEntity<Key> Get(Key key);
IEnumerable<E> GetRange(IEnumerable<Key> keys);
IEnumerable<E> GetAll();
// ..., Update, Delete methods
}
// Create an abstract class that will encapsulate the generic code
public abstract class Repository<K, E> where E:IEntity<K>>:IRepository<K, E>{
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<Key> 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 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
}
}
您现在有足够的工具来操作数据库,但如果需要,您可以使用活动模式。 一个简单的例子:
public class Person:IEntity<PersonKey>{
public PersonKey Key{get;}
public IEnumerable<Car> OwnedCars{
get{
CarRepository rep = DBSingletons.Cars;
return rep.GetByOwner(this.Key);
}
set{
// 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,因为它可能会变得非常复杂,特别是试图开发最通用的解决方案。
答案 1 :(得分:5)
我建议使用ORM,实体框架或NHibernate会做得很好。然后,您不必担心db上下文或创建SQL语句。
答案 2 :(得分:5)
首先,我想向您推荐文章Design Patterns for Data Persistence by Jeremy Miller。
有一些数据访问层模式:
答案 3 :(得分:2)
我建议您使用RepositoryBase进行所有这些常见操作。如果您决定使用ORM进行数据访问,最好在基于Generic Type存储库的存储库实现中进行思考。
这是一篇很好的文章:
http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/
答案 4 :(得分:1)
它过于陈旧但只是绕过这个问题,无法抗拒发表我的想法。
我发现Repository UnitOfWork与1有一些下降ORM是很好的方法。这最大限度地减少了大部分问题。
上面提到的UoW链接可以在Repository中注入。这增加了使用的灵活性。此外,所有数据库通信代码都集中在一个地方。该示例不完整,但是启动点。
上面链接中提到的存储库模式实际上是一个通用的基类。您可以为从中派生的每个具体存储库创建新类。
通用存储库被视为反模式;互联网上有很多文章可以解释它。
为什么通用存储库是反模式的?
GetById()
,标识符类型可能不同。我建议您阅读这些(2,3,4,5,{{3}})文章,解释为什么通用存储库是一种模式。
<强>解决方案:强>
在任何情况下,都不要将Generic Repository暴露给调用代码。另外,不要在具体的存储库中公开IQueryable
。