LINQ to SQLエンティティおよびデータコンテキストクラス:ビジネスオブジェクトのカプセル化
-
03-07-2019 - |
質問
LINQ to SQLエンティティクラスとデータコンテキストクラスをビジネスオブジェクトにカプセル化するお気に入りの方法は何ですか?
特定の状況で機能することがわかったものは何ですか?
特定のパターンを発明したか、特定のパターンを取り入れましたか
解決
私は、最もうまくいくと思うパターンを見つけました。少なくとも私の場合は。
部分クラスを使用してエンティティクラスを拡張します。エンティティの署名が変更されないように部分クラスを使用します( Delete
メソッドの DeleteOnSubmit
呼び出しを参照)。
小さな例を作成しました。データベースとLINQ to SQLクラスのセットアップの画像を次に示します。
そして、ここに私がビジネスロジックを実装する部分クラスがあります:
/// <summary>
/// This class extends BusinessLogicDataContext.Products entity class
/// </summary>
public partial class Product
{
/// <summary>
/// New up a product by column: dbo.Products.ProductId in database
/// </summary>
public Product(Int32 id)
{
var dc = new BusinessLogicDataContext();
// query database for the product
var query = (
from p in dc.Products
where p.ProductId == id
select p
).FirstOrDefault();
// if database-entry does not exist in database, exit
if (query == null) return;
/* if product exists, populate self (this._ProductId and
this._ProductName are both auto-generated private
variables of the entity class which corresponds to the
auto-generated public properties: ProductId and ProductName) */
this._ProductId = query.ProductId;
this._ProductName = query.ProductName;
}
/// <summary>
/// Delete product
/// </summary>
public void Delete()
{
// if self is not poulated, exit
if (this._ProductId == 0) return;
var dc = new BusinessLogicDataContext();
// delete entry in database
dc.Products.DeleteOnSubmit(this);
dc.SubmitChanges();
// reset self (you could implement IDisposable here)
this._ProductId = 0;
this._ProductName = "";
}
}
実装されたビジネスロジックの使用:
// new up a product
var p = new Product(1); // p.ProductId: 1, p.ProductName: "A car"
// delete the product
p.Delete(); // p.ProductId: 0, p.ProductName: ""
さらに:LINQ to SQLエンティティクラスは、本質的に非常にオープンです。これは、 dbo.Products.ProductId 列に対応するプロパティがゲッターとセッターの両方を実装することを意味します。このフィールドは変更できません。
私の知る限り、部分クラスを使用してプロパティをオーバーライドすることはできないため、通常はインターフェイスを使用してオブジェクトを絞り込むマネージャーを実装します:
public interface IProduct
{
Int32 ProductId { get; }
void Delete();
}
他のヒント
Repositoryパターンを使用してDataContextsをカプセル化する傾向があります。
LINQ2SQLを使用しながら、データレイヤーからPOCOオブジェクトを発行するより良い方法を見つけたいと思います。
IoCおよびT4-templatesを使用して、ストレージにLinq to Sqlを使用するアプリケーションを構築する方法のサンプルを公開しました。
http://daniel.wertheim.se/2010/03/14/linq-to-sql-how-to-separate-the-entities-and-the-datacontext/
今、私はLINQ to SQLエンティティクラスをビジネスオブジェクトとして使用して、それらを関数とサービスの間でやり取りしようとしています。
もちろん、データベースアクセス用の個別のエンティティクラスが必要です。そのため、ビジネスオブジェクトを変更せずにデータベースレイアウトを変更できます。
私もこのための良い解決策に興味があります!
Rob ConeryがまとめているMVCサンプルアプリのソースコードを確認します。
http://www.codeplex.com/mvcsamples/
彼には、LINQ to SQLクラスにマップする個別のエンティティレイヤーがあります。
データベースからクライアントコードをさらに分離する方法として、Entity FrameworkとLinq to Entitiesを使用していくつかの実験を行いましたが、使用するのが面倒で、パフォーマンスが心配でした。
現在のプロジェクトでは、Linq to SQLをデータレイヤーとして使用していますが、すべてのLinqクエリを実装する個別のクラスがあります。クラスは、Linq to SQLコンテキストで定義されたエンティティを返しますが、クエリはメソッドに隠されています。
CodeBetter.comのIan Cooper および Stephen Walther シリーズは非常に貴重です最初にPOCOエンティティを記述し、それを他の方法で行うのではなく、データベースにマッピングする必要があることを理解します(これは私がいつもしていたことです)。
OOモデルの別のレイヤー(OOプラクティスのより良いサポート)を持つというアイデアをいじっていますが、内部ではLINQ to SQLを使用しています。アイデアは、カスタムツールがコードを生成するために使用するxmlファイルを持つことです。 LINQ to SQLのエンティティは好みに合わせて整理されすぎているため、エンティティとして使用する新しいクラスを自動生成し、もちろんDataContextはクライアントコードに対して完全に非表示になります。 短い答えは、新しいエンティティクラスを作成しますが、基になるLINQ to SQLエンティティとDataContextを使用します。