数据访问层的设计模式

Dev*_*evT 12 .net c# design-patterns

你可能觉得这是家庭作业,因为我很抱歉.我搜索过但找不到合适的答案.

所以我的问题是:

我有几个类,每个类都有一个保存方法.所以我为数据库处理创建了一个单独的类.

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;
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我不认为使用DBConnection类实现所有类是合适的.

我的问题 :

  1. 什么设计模式适合克服这个问题?
  2. 将DBConnection创建为类是一种好习惯吗?(或者它应该是一个接口)

我使用Factory方法找到了一些关于DA图层的文章,但据我所知,这种模式不适合我的情况.

Joã*_*ões 13

通常,如果我不能使用任何现有框架,我同时使用Repository和Active模式.

为简单起见,您只能使用Repository模式.我通常这样定义它:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

您现在有足够的工具来操作数据库,但如果需要,您可以使用活动模式.一个简单的例子:

//  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();
}
Run Code Online (Sandbox Code Playgroud)

显然,在进行自己的实现时,必须考虑线程安全性,特别是在不同的实体存储库中使用事务.

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
    }
}
Run Code Online (Sandbox Code Playgroud)

只要确保你真的想要创建自己的DAL,因为它可能会变得非常复杂,特别是试图开发最通用的解决方案.


Ric*_*der 5

我建议使用ORM,实体框架或NHibernate会做得很好.然后,您不必担心db上下文或创建SQL语句.


Ser*_*nov 5

首先,我想向您推荐Jeremy Miller的文章Data Persistence的设计模式

有一些数据访问层模式:

  1. 活动记录模式Wiki详细信息)。
  2. 存储库模式详细信息)。