宿題だと感じるかもしれませんが、ごめんなさい。検索しましたが、適切な答えが見つかりませんでした。
だから私の質問は:
私にはいくつかのクラスがあり、各クラスには保存するメソッドがあります。そこで、データベース処理用に別のクラスを作成しました。
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レイヤーに関する記事をいくつか見つけましたが、私の知識によれば、そのパターンは私の状況に適していません。
通常、既存のフレームワークを使用できない場合は、リポジトリパターンとアクティブパターンの両方を使用します。
簡単にするために、リポジトリパターンのみを使用できます。私は通常、次のように定義します。
// 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を作成したいことを確認してください。
ORM、Entity Framework、またはNHibernateを使用するとうまくいくことをお勧めします。そうすれば、dbコンテキストについて心配したり、SQLステートメントを作成したりする必要はありません。
まず、記事 Jeremy Millerによるデータ永続性のデザインパターン をお勧めします。
いくつかのデータアクセス層パターンがあります。
このすべての一般的な操作には、RepositoryBaseを使用することをお勧めします。データアクセスにORMを使用する場合は、ジェネリック型リポジトリに基づくリポジトリの実装を検討することをお勧めします。
これはそれについての良い記事です:
http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/
それは古すぎますが、ちょうどこの質問に出くわし、私の考えを投稿することに抵抗できませんでした。
Repository with nitOfWork with some descentORMが良いアプローチであることがわかりました。これにより、ほとんどの問題が最小限に抑えられます。
上記のリンクで言及されているUoWは、リポジトリに挿入できます。これにより、使用の柔軟性が高まります。また、すべてのDB通信コードは1か所に一元化されています。例は完全ではありませんが、スタートアップポイントです。
上記のリンクに記載されているリポジトリパターンは、実際には一般的な基本クラスです。派生する具象リポジトリごとに新しいクラスを作成できます。
ジェネリックリポジトリはアンチパターンと見なされます。それを説明するインターネット上の記事はたくさんあります。
ジェネリックリポジトリがアンチパターンである理由
GetById()
の場合、識別子のタイプは異なる場合があります。これらを読むことをお勧めします( 1 、 2 、、 4 、 5 )ジェネリックリポジトリがアンチパターンである理由を説明する記事。
解決策:
いずれの場合も、ジェネリックリポジトリを呼び出し元のコードに公開しないでください。また、具体的なリポジトリからIQueryable
を公開しないでください。