オブジェクトはどこで3層モデルのデータをマージ/結合しますか?
-
24-10-2019 - |
質問
その可能性が高いのは、単純な3層の問題です。私はこれにベストプラクティスを使用していることを確認したいだけで、私はまだ構造を持つ家族ではありません。
3つの層があります:
- GUI:プレゼンテーションレイヤー用ASP.NET(最初のプラットフォーム)
- BAL:Business-LayerはC#のWebサーバーでロジックを処理するため、Webforms/MVC + Webサービスに使用できます。
- DAL:linqからsqlからsql in the data-layer、business objectsを返してください。
- DB:SQLはMicrosoft SQL-Server/Express(まだ決定されていません)になります。
人]のデータベースがあるセットアップについて考えてみましょう。それらはすべて複数の[アドレス] esを持つことができ、すべての[郵便]および対応する都市名の完全なリストがあります。
契約は、他のテーブルから多くの詳細に参加したことです。
{関係}/[表
- 人]:1 --- n:{personAddress}:m --- 1:[住所
- 住所]:n --- 1:[郵便局?
今、私たちは人のためにDALを構築したいと思っています。ペンボはどのように見えるべきですか、そして参加はいつ発生しますか?すべての都市名と可能なアドレスPRを取得するのはビジネス層の問題ですか?人?それとも、DALがBALにPersonboを返す前にこれをすべて完了する必要がありますか?
Class PersonBO
{
public int ID {get;set;}
public string Name {get;set;}
public List<AddressBO> {get;set;} // Question #1
}
// Q1:ペンボを返す前にオブジェクトを取得しますか?代わりに配列にする必要がありますか?または、これはnティア/3層では完全に間違っていますか?
Class AddressBO
{
public int ID {get;set;}
public string StreetName {get;set;}
public int PostalCode {get;set;} // Question #2
}
// Q2:検索を行うのですか、それとも後で検索するために郵便局を残しますか?
誰がどのオブジェクトを引っ張るかを説明できますか?建設的な批判は大歓迎です。 :o)
解決
あなたはホイールを再発明しています。 Ormsはすでにあなたのためにこの問題のほとんどを解決しており、あなたは自分自身をするのが少し難しいと感じるでしょう。
LinqからSQL、Entity Framework、およびNhibernateのようなormsがこれを行う方法は、 怠zyなロード 協会(オプションで熱心な負荷でオーバーライデンすることができます)。
あなたがプルアップするとき Person
, 、ロードしません Address
具体的にそれを求めるまで、その時点でデータベースへの別の往復が発生します(レイジーロード)。また、クエリごとに指定することもできます。 Address
のためにロードされます 毎日 人(熱心な負荷)。
ある意味では、この質問を使用すると、基本的には怠zyまたは熱心な負荷を実行する必要があるかどうかを尋ねています。 AddressBO
のために PersonBO
, 、そして答えは次のとおりです。普遍的に機能する単一のアプローチはありません。 デフォルトで おそらく怠zyな負荷が必要です。そうすれば、不必要な参加をたくさんしないようにする必要があります。これをやってのけるためには、あなたはあなたを構築する必要があります PersonBO
DALへの参照を維持する怠zyなローディングメカニズムを使用します。ただし、「ビジネスアクセス」ロジックに組み込む必要があることを、積極的にロードするオプションが必要です。
別のオプションは、多くの異なるテーブルから入力された特定のプロパティを持つ高度にカスタマイズされたデータセットを返す必要がある場合、Aを返さないことです。 PersonBO
まったくですが、代わりにaを使用します データ転送オブジェクト (DTO)。デフォルトのレイジーロードメカニズムを実装すると、これを熱心なバージョンに置き換えることができます。
参考までに、データアクセスフレームワークの怠zyなローダーは、通常、関連付け自体の読み込みロジックで構築されます。
public class PersonBO
{
public int ID { get; set; }
public string Name { get; set; }
public IList<AddressBO> Addresses { get; set; }
}
これは単なるポコであり、魔法は実際のリストの実装で起こります。
// NOT A PRODUCTION-READY IMPLEMENTATION - DO NOT USE
internal class LazyLoadList<T> : IList<T>
{
private IQueryable<T> query;
private List<T> items;
public LazyLoadList(IQueryable<T> query)
{
if (query == null)
throw new ArgumentNullException("query");
this.query = query;
}
private void Materialize()
{
if (items == null)
items = query.ToList();
}
public void Add(T item)
{
Materialize();
items.Add(item);
}
// Etc.
}
(これは明らかに生産グレードではなく、テクニックを実証するためだけです。クエリから始めて、必要になるまで実際のリストを実現しないでください。)