5

モデルエンティティに適合しない、または一部を拡張する、リポジトリからアドホック(ケースバイケースのカスタム)データを返すための推奨される方法は何ですか?

101の例は、ユビキタスなhellowordアプリケーションであるブログシステムです。投稿エントリに投稿エンティティに存在しない追加情報が含まれている投稿のリストをロードするとします。コメントの数と最後のコメントの日時だとしましょう。単純な古いSQLを使用し、データベースから直接データを読み取る場合、これは非常に簡単です。各投稿のコメントのコレクション全体をロードする余裕がなく、1回のデータベースヒットでそれを実行したい場合、リポジトリパターンを使用して最適に実行するにはどうすればよいですか?この状況で一般的に使用されるパターンはありますか?ここで、各ページにわずかに異なるカスタムデータが必要であり、完全な階層(パフォーマンス、メモリ要件など)をロードできない、適度に複雑なWebアプリケーションがあるとします。

いくつかのランダムなアイデア:

  1. カスタムデータで入力できるプロパティのリストを各モデルに追加します。

  2. サブクラスモデルエンティティはケースバイケースで、サブクラスごとにカスタムリーダーを作成します。

  3. LINQを使用して、アドホッククエリを作成し、匿名クラスを読み取ります。

注:最近、同様の質問をしましたが、一般的すぎるようで、あまり注目されていませんでした。

例:

以下の回答の提案に基づいて、より具体的な例を追加します。これが私が説明しようとしていた状況です:

IEnumarable<Post> posts = repository.GetPostsByPage(1);
foreach (Post post in posts)
{

    // snip: push post title, content, etc. to view

    // determine the post count and latest comment date
    int commentCount = post.Comments.Count();
    DateTime newestCommentDate = post.Comments.Max(c => c.Date);

    // snip: push the count and date to view

}

余分なことを何もせずに既成のORMを使用すると、n + 1クエリ、または1つのクエリですべての投稿とコメントが読み込まれる可能性があります。ただし、最適には、投稿のタイトル、本文など、コメント数、最新のコメント日付を含む投稿ごとに1行を返すSQLを1つだけ実行できるようにしたいと思います。これはSQLでは簡単です。問題は、私のリポジトリがこのタイプのデータを読み取ってモデルに適合させることができないことです。最大日付とカウントはどこに行きますか?

私はそれをどのように行うかを尋ねていません。リポジトリにメソッドを追加したり、新しいクラスや特別なエンティティを追加したり、 LINQを使用したりするなど、いつでもそれを行うことができますが、私の質問は次のとおりです。どうしてリポジトリパターンと適切なモデル駆動型開発が広く受け入れられているのか、それでも、この一見非常に一般的で基本的なケースに対処していないようです。

4

5 に答える 5

1

最初の質問で概説した問題を緊急に解決する必要があったため、次の解決策に頼りました。各モデル エンティティにプロパティ コレクション (ディクショナリ) を追加し、DAL が必要に応じてカスタム データを貼り付けます。ある種の制御を確立するために、プロパティ コレクションは指定されたクラスのインスタンスによってキー設定され、単純なデータ タイプ (整数、日付など) のみをサポートします。 . これが解決する典型的なケースは、完全に取り込まれたコレクションではなく、そのサブコレクションのカウントを使用してエンティティをロードすることです。これはおそらくソフトウェア設計の賞を受賞するものではないと思いますが、私たちのケースでは最もシンプルで実用的なソリューションでした.

于 2009-03-15T21:13:18.197 に答える
0

RDBM に縛られていない場合は、CouchDB や Amazons SimpleDB などのデータベースを検討することをお勧めします。あなたが説明していることは、CouchDB ビューでは些細なことです。これはおそらく特定の質問に実際に答えるものではありませんが、根本的に異なるオプションを検討することをお勧めします。

于 2009-04-01T03:06:10.900 に答える
0

このために、私は通常、RepositoryStatus と、データ転送オブジェクト (DTO) として機能する Status クラスを用意しています。Status クラスは、(同じ理由で) 私のアプリケーション サービス層で使用され、そこから RepositoryStatus が継承されます。次に、このクラスを使用して、エラー メッセージ、応答オブジェクトなどをリポジトリ レイヤーから返すことができます。このクラスは、任意のオブジェクトを受け入れて受信側にキャストするという点で汎用的です。

ステータスクラスは次のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RanchBuddy.Core.Domain;
using StructureMap;

namespace RanchBuddy.Core.Services.Impl
{
    [Pluggable("Default")]
    public class Status : IStatus
    {
        public Status()
        {
            _messages = new List<string>();
            _violations = new List<RuleViolation>();
        }

        public enum StatusTypes
        {
            Success,
            Failure
        }

        private object _object;
        public T GetObject<T>()
        {
            return (T)_object;
        }
        public void SetObject<T>(T Object)
        {
            _object = Object;
        }

        private List<string> _messages;
        public void AddMessage(string Message)
        {
            _messages.Add(Message);
        }
        public List<string> GetMessages()
        {
            return _messages;
        }
        public void AddMessages(List<string> Messages)
        {
            _messages.AddRange(Messages);
        }

        private List<RuleViolation> _violations;
        public void AddRuleViolation(RuleViolation violation)
        {
            _violations.Add(violation);
        }
        public void AddRuleViolations(List<RuleViolation> violations)
        {
            _violations.AddRange(violations);
        }
        public List<RuleViolation> GetRuleViolations()
        {
            return _violations;
        }
        public StatusTypes StatusType { get; set; }
    }
}

ここに RepositoryStatus があります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RanchBuddy.Core.Services.Impl;
using StructureMap;

namespace RanchBuddy.Core.DataAccess.Impl
{
    [Pluggable("DefaultRepositoryStatus")]
    public class RepositoryStatus : Status, IRepositoryStatus
    {

    }
}

ご覧のとおり、RepositoryStatus はまだ特別なことを行っておらず、Status オブジェクトのユーティリティに依存しているだけです。しかし、後日延長する権利を留保したかったのです!

私はそこにいる頑固者の何人かが、あなたがプルイストであるならこれを使用すべきではないと述べていると確信しています...しかし、私は時々あなたが単に返されたオブジェクト以上のものを渡す必要があるというあなたの痛みを知っています!

于 2009-06-13T16:57:32.167 に答える
0

ここで空中で発砲するだけで、問題が何であるかを本当に理解しているとは言えません。

  • 特定のエンティティを追加して、必要な情報をカプセル化します
  • プロパティ コメントを投稿に追加します。(なぜこれがすべてのコメントを取得する必要があるのか​​ わかりません-ロードしている特定の投稿のコメントを取得するだけで済みます)
  • 遅延読み込みを使用して、プロパティにアクセスするときにのみコメントを取得します

プラットフォーム、言語、および O/R マッパーを固有のものにすると、質問への回答が得られる可能性が高くなると思います (LINQ について言及したので、.NET C# または VB のようです。LINQ 2 SQL? エンティティ フレームワーク? 何か他のもの?)

于 2009-03-07T09:33:31.083 に答える