2012-12-06 67 views
10

您可能會覺得這是作業,因爲我很抱歉。我已經搜索,但無法找到正確的答案。數據訪問層的設計模式

所以我的問題是:

我有幾個類和每個類都有一個方法來保存。所以我爲數據庫處理創建了一個單獨的類。

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類實現所有的類。

我的問題:

  1. 什麼設計模式適合於解決這個問題?
  2. 創建DBConnection作爲類是不錯的做法? (或者它應該是一個接口)

我發現了一些關於使用工廠方法DA層的文章,但根據我的知識,該模式不適合我的情況。

+0

看看存儲庫模式,它聽起來像它可能會幫助你。 – BenjaminPaul

+0

如果您的代碼中的用戶名和密碼是真實的,您應該立即隱藏它們。 –

+0

你想創建一個Singleton嗎?如果是這樣,你做錯了。 –

回答

10

通常情況下,如果我不能使用任何現有的框架,我同時使用存儲庫和主動模式。

爲了簡單起見,您只能使用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 
     } 
    } 
} 

顯然,做你自己的實現時,你必須考慮到線程安全取得良好的使用事務處理的,特別是跨diferent實體庫。

// 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,因爲它可以結束extremelly複雜beeing,特別是努力開發最通用的解決方案。

+1

這是否編譯?例如,公共接口IRepository >應該是公共接口IRepository 其中E:IEntity (請注意< >),應該不是嗎?總的來說,雖然很棒! – crunchy

+0

感謝您的提示!我相信我在記事本+ +中編寫了這段代碼,所以當時我無法測試它!修正添加! –

5

我建議使用ORM,實體框架或NHibernate會很好。然後,您不必擔心數據庫上下文或創建SQL語句。

+0

thanx你的幫助...但我喜歡學習他們的理論 – DevT

+1

不用擔心這一點。但爲什麼不閱讀NHibernate的源代碼來學習如何設計一個存儲庫。或者看看Active Record,它比NHibernate更容易閱讀。或者只是將它作爲@Sergey最有可能完成的(我給了u + 1 @sergey)。 –

+0

好....再次thanx ... – DevT

1

它太舊了,但只是來解決這個問題,忍不住發表了我的想法。

我發現RepositoryUnitOfWork一些血統ORM是不錯的辦法。這可以最大限度地減少大部分問題。

的UOW在上面提到的鏈接可以在存儲庫被注入。這增加了使用的靈活性。而且,所有數據庫通信代碼都集中在一個地方。這個例子並不完整,而是一個啓動點。

上述鏈接中提到的存儲庫模式實際上是一個通用的基類。您可以爲每個從其派生的具體存儲庫創建新類。

通用存儲庫被認爲是反模式;互聯網上有很多文章解釋它。

爲什麼通用倉庫是反模式?

  1. 存儲庫是被建模的域的一部分,該域不是通用的。
    • 並不是每一個實體可以被刪除。
    • 並不是每一個實體可以加入
    • 不是每個實體都有一個存儲庫。
    • 查詢各式各樣,存儲庫API變得與實體本身一樣獨特。
    • 對於GetById(),標識符類型可能不同。
    • 更新特定字段(DML)不可能。
  2. 通用查詢機制是一個ORM的責任。
    • 大多數奧姆斯的揭露與一般存儲庫非常類似的實現。
    • 存儲庫應該使用ORM公開的通用查詢機制實現對實體的特定查詢。
  3. 複合主鍵的工作是不可能的。
  4. 無論如何它泄漏了服務中的DAL邏輯。
    • 謂詞條件如果接受作爲參數需要從服務層提供的。如果這是ORM特定的類,它會將ORM泄漏到服務中。

解決方案:

  1. 有一個由混凝土包裹倉庫的通用存儲庫。這樣,您可以控制公共接口,但仍具有來自通用存儲庫的代碼重用優勢。
  2. 使用通用存儲庫,但使用組合而不是繼承,並且不要將其作爲合同公開給域。