3

次の単純な POCO、国と州を想定します。

public partial class Country
{
    public Country()
    {
        States = new List<State>();
    }
    public virtual int CountryId { get; set; }
    public virtual string Name { get; set; }
    public virtual string CountryCode { get; set; }
    public virtual ICollection<State> States { get; set; }
}

public partial class State
{
    public virtual int StateId { get; set; }
    public virtual int CountryId { get; set; }
    public virtual Country Country { get; set; }
    public virtual string Name { get; set; }
    public virtual string Abbreviation { get; set; }
}

ここで、次のような単純なリポジトリがあるとします。

public partial class CountryRepository : IDisposable
{
    protected internal IDatabase _db;

    public CountryRepository()
    {
        _db = new Database(System.Configuration.ConfigurationManager.AppSettings["DbConnName"]);
    }

    public IEnumerable<Country> GetAll()
    {
        return _db.Query<Country>("SELECT * FROM Countries ORDER BY Name", null);
    }

    public Country Get(object id)
    {
        return _db.SingleById(id);
    }

    public void Add(Country c)
    {
        _db.Insert(c);
    }

    /* ...And So On... */
}

通常、私の UI では、すべての子 (状態) を表示するわけではありませんが、集計数は表示します。したがって、私の国のリスト ビュー モデルは次のようになります。

public partial class CountryListVM
{
    [Key]
    public int CountryId { get; set; }
    public string Name { get; set; }
    public string CountryCode { get; set; }
    public int StateCount { get; set; }
}

基になるデータ プロバイダー (Entity Framework、NHibernate、PetaPoco など) を UI レイヤーで直接使用している場合、次のようなことを簡単に行うことができます。

IList<CountryListVM> list = db.Countries
    .OrderBy(c => c.Name)
    .Select(c => new CountryListVM() {
        CountryId = c.CountryId,
        Name = c.Name,
        CountryCode = c.CountryCode,
        StateCount = c.States.Count
    })
    .ToList();

しかし、リポジトリまたはサービス パターンを使用している場合は、データ レイヤーへの直接アクセスを抽象化します。私のオプションは次のとおりです。

  1. データが入力された States コレクションで Country を返し、UI レイヤーにマップします。このアプローチの欠点は、実際に必要な量よりも多くのデータを返すことです。

    -また-

  2. すべてのビュー モデルを共通 dll ライブラリに入れ (MVC アプリの Models ディレクトリに置くのではなく)、リポジトリを展開して、ドメイン pocos だけでなく特定のビュー モデルを返します。このアプローチの欠点は、UI 固有のもの (MVC データ検証注釈) を以前のクリーンな POCO にリークしていることです。

    -また-

  3. 他のオプションはありますか?

このようなことをどのように処理していますか?

4

4 に答える 4

2

私たちが何をするかは、プロジェクトのアーキテクチャに大きく依存します。通常は..リポジトリの上に、このロジックを処理するサービスがあります。サービスは、どのデータをロードするためにどのリポジトリを使用するかを決定します。流れはUI→Controller→Service→Repositories→DB。UI および/またはコントローラーは、リポジトリーまたはその実装についての知識がありません。

また、StateCount = c.States.Count間違いなく States リストに値が入力されることは間違いありません..そうではありませんか? 私はそれがNHibernateであると確信しています(LazyLoadingにより余分な選択がDBに送信されます)。

于 2012-10-10T21:26:12.543 に答える
2

1 つのオプションは、クエリを既存のインフラストラクチャから完全に分離することです。これは、CQRS設計の実装になります。この場合、ドメイン オブジェクトをバイパスして、「Thin Read Layer」を使用してデータベースに直接クエリを発行できます。既存のオブジェクトと ORM は実際に邪魔になっています。CQRS を使用すると、「コマンド側」を分離して、「クエリ側」とはまったく異なる一連の技術を持つことができます。それぞれが独自の仕事をするように設計されています。相手の要求に妥協することなく。

はい、文字通り、既存のアーキテクチャをそのままにして、Dapperのようなものを使用して、MVC コントローラーから直接これを行うことをお勧めします (テストされていないコード サンプルに注意してください)。たとえば、次のようになります。

int count = 
    connection.Query<int>(
        "select count(*) from state where countryid = @countryid", 
        new { countryid = 123 } );
于 2012-10-10T21:27:31.310 に答える
1

正直なところ、あなたの質問は私に数日間考えさせられました. 非正規化が正しい解決策であると考える傾向がますます強くなっています。

ほら、ドメイン駆動設計の主なポイントは、問題のドメインにモデリングの決定を任せることです。現実世界の国の実体を考えてみましょう。国には州のリストがあります。ただし、特定の国にいくつの州があるかを知りたい場合、百科事典の州のリストを調べて数えることはありません。国の統計を見て、そこにある州の数を確認する可能性が高くなります。

私見、同じ動作がドメインモデルに反映されるはずです。この情報を国のプロパティに含めるか、一種の CountryStatistics オブジェクトを導入することができます。どのアプローチを選択する場合でも、それは国全体の一部でなければなりません。集約の整合性境界にあると、状態が追加または削除された場合に整合性のあるデータが保持されます。

于 2012-10-13T17:55:59.973 に答える
1

いくつかの他のアプローチ:

  • states コレクションがあまり変更されないことが予想される場合は、多少の非正規化を許可することができます - "NumberOfStates" プロパティを Country オブジェクトに追加します。クエリは最適化されますが、余分なフィールドに正しい情報が保持されていることを確認する必要があります。

  • NHibernate を使用している場合は、ExtraLazyLoading を使用できます。別の select が発行されますが、Count が呼び出されたときにコレクション全体が読み込まれません。詳細はこちら: nHibernate Collection Count

于 2012-10-10T21:21:02.567 に答える