0

ASP.NET MVC 3 アプリケーションで EF Code First アプローチを使用していますが、ホイールを再作成する代わりに、カスタム リポジトリ クラスが提供するために拡張できる堅実なベース リポジトリ クラスが既に存在するかどうか疑問に思っていました。デフォルトの機能 (基本的な CRUD など)。

だから、このようなもの...

public class CustomerRepository : BaseRepository { ... }

... したがって、そのままで Customer オブジェクトを操作するデフォルトの方法を提供します。次に、ICustomerRepository を MVC コントローラーに挿入し、そこで機能を利用できるようにしたいと考えています。

私はNHibernateで同様のことをしたので、このようなものがすでに存在していると確信しています。

ありがとう

4

4 に答える 4

5

いいえ、EF 自体以外に組み込みのリポジトリはありません (それ自体が Unit of Work パターンの実装であり、DbSet は基本的にリポジトリです)。

現在、汎用リポジトリに真の価値があるかどうかについて、ソフトウェア コミュニティで議論が交わされています。テスト目的で、多くの人が主張するように、それらは簡単な単体テストを提供します。モック化されたリポジトリは実際のリポジトリと同じように動作しないため、単体テスト リポジトリは役に立たないと言う人もいます (モック化されたリポジトリには存在しない linq -> Sql 変換レイヤーのため)。

多くの人が、単体テストではなく、SqlLite のようなメモリ内データベースを使用して EF に対して統合テストを行うことを提案しています。

それでも、リポジトリを使用したい場合は、さまざまなスタイルや方法の例がネット上にたくさんあります。または、自分でロールすることもできます。MS は提供していません。

于 2012-07-11T16:02:44.330 に答える
3

私の経験では、EF は DbSet を通じてこのパターンを既に実装しているため、独自のリポジトリを作成することは冗長です。

最近のプロジェクトで MVC3 + EF Code Fisrt を使用しました。いくつかのチュートリアルに従って汎用リポジトリの実装を開始しましたが、すぐに不要で冗長なコードをたくさん書いていることに気付きました。実際、リポジトリには、DbSet の多くの機能が隠されているだけでした。最後に、それらを削除して、DbContext と DbSet を直接操作することにしました。

しかし、単純な CRUD 操作を超えた複雑なビジネス ロジックはどうでしょうか。

クエリや複数の CRUD 操作などのすべての複雑な機能を、サービス レイヤーを介して公開しました。機能ごとに異なるサービス クラスを構築できます。たとえば、AccountService を記述して、ユーザー アカウントに関連するすべての機能を管理できます。このようなもの:

public class AccountService {

    private MyContext ctx;

    public AccountService(DbContext dbContext) {
        this.ctx = (MyContext)dbContext;
    }

    /// <summary>
    /// Gets the underlying DbContext object.
    /// </summary>
    public DbContext DbContext {
        get { return ctx; }
    }

    /// <summary>
    /// Gets the users repository.
    /// </summary>
    public DbSet<User> Users {
        get {return ctx.Users;}
    }

    public bool ValidateLogin(string username, string password) {
        return ctx.Users.Any(u => u.Username == username && u.Password == password);
    }

    public string[] GetRolesForUser(string username) {
        var qry = from u in ctx.Users
                  from r in u.Roles
                  where u.Username == username
                  select r.Code;

        return qry.ToArray<String>();
    }

    public User CreateUser(string username, string password) {
        if (String.IsNullOrWhiteSpace(username)) throw new ArgumentException("Invalid user name");
        if (String.IsNullOrWhiteSpace(password)) throw new ArgumentException("Invalid password");

        User u = new User {
            Username = username.Trim().ToLower(),
            Password = password.Trim().ToLower(),              
            Roles = new List<Role>()
        };

        ctx.Users.Add(u);
        ctx.SaveChanges();

        return u;
    }

依存性注入はどうですか?

このアプローチを使用して、挿入する必要があるのは DbContext だけです。サービス クラスには、DbContext を受け取るコンストラクターがあります。そのため、コントローラー コンストラクターがサービス インスタンスを取得すると、DbContext が注入されます。

編集: コード例
これは、コントローラーがどのように見えるかについてのコード例です。

public class HomeController : Controller {

    private readonly AccountService accountService; 

    public AccountController(AccountService accountService) {
        this.accountService = accountService;
    }
}

そして、これは NInject を使用した DI 構成である可能性があります。

private static void RegisterServices(IKernel kernel) {
    kernel.Bind<MyContext>().ToSelf().InRequestScope();
    kernel.Bind<DbContext>().ToMethod(ctx => ctx.Kernel.Get<MyContext>());
}

単体テストはどうですか?

サービス層クラスごとに特定のインターフェイスを構築し、必要な場所でそれをモックできます。

于 2012-07-11T19:21:02.580 に答える
0

私の友人である Sacha Barber が、これらのアイデアのいくつかを取り上げた素晴らしい記事を書きました。

リンクはこちらからご覧いただけます。

RESTful WCF / EF POCO / 作業単位 / リポジトリ / MEF: 1/2

于 2012-07-11T16:01:31.967 に答える
0

EF には、 という基本クラスがありDbContextます。タイプのプロパティを追加できますDbSet<TEntity>

これにより、次のようなことができます。

public class User {
    public int Id { get; set; }
    public string Name { get; set; }
}

public class DatabaseContext : DbContext {
    public DbSet<User> Users { get; set; }
}

これを次のように使用できます。

using(var db = new DatabaseContext()) {
    User jon = new User {Name = "Jon Smith"};
    db.Users.Add(jon);
    db.SaveChanges();
    var jonById = db.Users.Single(x => x.Id == 1);
}

さらに抽象化が必要な場合は、EF Entity Framework 4 CTP 4 / CTP 5 Generic Repository Pattern and Unit Testableを中心とした汎用リポジトリの構築に関するこの投稿を参照してください。DbContext を直接使用するだけでなく、ジェネリック リポジトリを追加することで省略形が本当に役立つかどうかを判断する必要があります。

于 2012-07-11T16:06:42.270 に答える