12

これは宿題だと思うかもしれません。申し訳ありません。検索しましたが、適切な答えが見つかりませんでした。

だから私の質問は:

いくつかのクラスがあり、各クラスには保存するメソッドがあります。そこで、データベース処理用に別のクラスを作成しました。

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 をクラスとして作成するのは良い方法ですか? (または、インターフェイスである必要があります)

Factory メソッドを使用した DA レイヤーに関する記事をいくつか見つけましたが、私の知る限り、そのパターンは私の状況には適していません。

4

5 に答える 5

14

通常、既存のフレームワークを使用できない場合は、リポジトリパターンとアクティブパターンの両方を使用します。

簡単にするために、リポジトリパターンのみを使用できます。私は通常、次のように定義します。

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を作成する必要があることを確認してください。

于 2012-12-06T19:11:33.997 に答える
5

まず、Jeremy Miller による記事「データ永続化のためのデザイン パターン」をお勧めします。

いくつかのデータ アクセス層パターンがあります。

  1. アクティブなレコード パターン( wiki詳細情報)。
  2. リポジトリ パターン(詳細情報)。
于 2012-12-06T17:30:22.033 に答える
4

ORM、Entity Framework、または NHibernate を使用することをお勧めします。次に、db コンテキストについて心配したり、SQL ステートメントを作成したりする必要はありません。

于 2012-12-06T17:26:23.207 に答える
2

このすべての一般的な操作には、RepositoryBase を使用することをお勧めします。データ アクセスに ORM を使用する場合は、ジェネリック タイプ リポジトリに基づくリポジトリの実装を検討することをお勧めします。

これについての良い記事は次のとおりです。

http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/

于 2012-12-06T17:49:37.333 に答える
2

古すぎますが、この質問にたどり着いたばかりで、私の考えを投稿することに抵抗できませんでした.

いくつかの降下 ORM を使用した UnitOfWork を使用したリポジトリが良いアプローチであることわかりました。これにより、ほとんどの問題が最小限に抑えられます。

上記のリンクに記載されている UoW は、リポジトリに挿入できます。これにより、使用の自由度が高まります。また、すべての DB 通信コードは 1 か所に集中化されています。この例は完全ではありませんが、開始点です。

上記のリンクで言及されているリポジトリ パターンは、実際には一般的な基本クラスです。そこから派生する具象リポジトリごとに新しいクラスを作成できます。

汎用リポジトリはアンチ パターンと見なされます。それを説明するインターネット上の多くの記事があります。

汎用リポジトリがアンチパターンなのはなぜですか?

  1. リポジトリはモデル化されるドメインの一部であり、そのドメインは一般的ではありません。
    • すべてのエンティティを削除できるわけではありません。
    • すべてのエンティティを追加できるわけではありません
    • すべてのエンティティにリポジトリがあるわけではありません。
    • クエリは大きく異なります。リポジトリ API は、エンティティ自体と同じくらい一意になります。
    • の場合GetById()、識別子のタイプが異なる場合があります。
    • 特定のフィールド (DML) を更新できません。
  2. 一般的なクエリ メカニズムは、ORM の役割です。
    • ほとんどの ORM は、汎用リポジトリとよく似た実装を公開しています。
    • リポジトリは、ORM によって公開される汎用クエリ メカニズムを使用して、エンティティの SPECIFIC クエリを実装する必要があります。
  3. 複合キーを操作することはできません。
  4. とにかくサービスでDALロジックをリークします。
    • パラメータとして受け入れる場合の述語基準は、サービス層から提供される必要があります。これが ORM 固有のクラスである場合、ORM がサービスにリークします。

ジェネリック リポジトリが anit-pattern である理由を説明しているこれらの (1、2、3、4、5)記事読むこと勧めします

解決:

  1. 具象リポジトリでラップされた抽象的な汎用リポジトリを作成します。こうすることで、パブリック インターフェイスを制御できますが、汎用リポジトリから得られるコード再利用の利点も得られます。
  2. 汎用リポジトリを使用しますが、継承の代わりに構成を使用し、コントラクトとしてドメインに公開しないでください。

いずれの場合も、Generic Repository を呼び出し元のコードに公開しないでください。IQueryableまた、具体的なリポジトリから公開しないでください。

于 2018-02-07T13:55:17.250 に答える