4

ASP.NET MVC と Entity Framework を使用して新しい小さなプロジェクトを開始しています。(SQL Server - 約 20 の DB テーブル) 過去のプロジェクトで Linq2SQL を使用しましたが、時代遅れのようです。

私はEFのリポジトリパターンの使用に関する多くの投稿を読みました(長所と短所)、私にとっては、リポジトリパターンなしでコーディングする方が良い/簡単に思えます。

次のプロジェクト アーキテクチャを作成しました。

namespace MySite.Models
{
    public class User
    {
        public Int32 ID { get; set; }
        public String Email { get; set; }
        public String Password { get; set; }
        public String Name { get; set; }
        public Int32 Gender { get; set; }
    }
}

namespace MySite.DAL
{
    public class Users
    {
       public static IEnumerable<User> GetUsers()
        {
            using (var context = new DatingSiteContext())
            {
                return context.Users.ToList();
            }
        }

        public static User GetUserByID(int id)
        {
            using (var context = new DatingSiteContext())
            {
                return context.Users.Find(id);
            }
        }
}

namespace MySite.Controllers
{
    public class HomeController : Controller
    {

        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            var users = DAL.Users.GetUsers();

            return View(users);
        }
    }
}
  • このように EF を使用することの欠点は何ですか? (単体テストのサポートがない場合を除く)
  • DAL への呼び出しごとに新しい DbContext を作成するのは間違っていますか? パフォーマンスのヒットはありますか?
  • EF を使用するための他の推奨構造はありますか? 例?:)
  • 新しいプロジェクトで Linq2SQL を使用しますか?

ありがとうございました。

編集:

GetUsers() および GetUserByID() 内のコードは単なる例です。データベースからすべてのレコードを返すことは悪い習慣であることを理解しています (ページングまたは欠落しているフィルター)

4

3 に答える 3

7

あなたは実際にリポジトリを作成しただけですが、それを「データ アクセス レイヤー」と呼んでいますが、これは私の意見では、Entity Framework がデータ アクセス レイヤーであるため、適切な名前ではありません。リポジトリは、データ アクセス層 (この場合は Entity Framework) の上の抽象化です。


DAL への呼び出しごとに新しい DbContext を作成するのは間違っていますか? パフォーマンスのヒットはありますか?

DbContextいいえ、問題ありませんが、 の 1 つのインスタンスでエンティティをフェッチし、別のインスタンスでエンティティを更新しようとすると、問題が発生する可能性があります。


新しいプロジェクトで Linq2SQL を使用しますか?

いいえ、Microsoft は Entity Framework を L2SQL の後継として提案し、積極的な開発は停止しました。


EF を使用するための他の推奨構造はありますか? 例?:)

使用するアプローチ、特定のリポジトリでは、多くの冗長コードが発生します。インターフェイスを実装する汎用リポジトリを作成できます。

public interface IRepository<TEntity> 
    where TEntity : class, new()
{
    IEnumerable<TEntity> GetAll();

    TEntity GetById(int id);

    IQueryable<TEntity> Table { get; }
}

そしてこれの実装:

public EfRepository<TEntity> : IRepository<TEntity>
    where TEntity : class, new()
{
    private readonly DatingSiteContext _context;

    public EfRepository()
    {
        _context = new DatingSiteContext();
    }

    private IDbSet<TEntity> Entities
    {
        get
        {
            return _context.Set<TEntity>();
        }
    }

    public IEnumerable<TEntity> GetAll()
    {
        return Entities.ToList();
    }

    public TEntity GetById(int id)
    {
        return Entities.Find(id);
    }

    public IQueryable<TEntity> Table 
    { 
        get { return Entities; }
    }   
}

このリポジトリは、次のようにコントローラーで使用できます。

public class HomeController : Controller
{
    private readonly IRepository<User> _userRepository;

    public HomeController()
    {
        _userRepository = new EfRepository<User>();
    }

    public ActionResult Index()
    {
        var users = _userRepository.GetAll();
        var inactiveUsers = _userRepository.Table.Where(u => !u.Active).ToList();
    }
}

この汎用リポジトリを使用すると、モック リポジトリを作成できます。

public class FakeUserRepository : IRepository<User> 
{ 
    // ... 
}


このアプローチは大量のコードのように見えるかもしれませんが、エンティティ タイプの量が増えるにつれて、IRepository<>コントローラーでフィールドを作成するだけで済むため、多くの作業を節約できます。IQueryable<>それでも、遅延実行を可能にするプロパティには多くの柔軟性があります。

これが最善の方法だと言っているわけではありません。私がプロジェクトで定期的に使用している方法です。私は通常、コントローラーとリポジトリーの間にビジネス (サービス) レイヤーを作成していると言わざるを得ません。ビジネス ロジックと複雑な Linq クエリ (およびその実行) をそこに保持します。DbContextまた、オブジェクト (インスタンスやサービスなど)の有効期間を処理する IoC コンテナーも使用します。詳細については、この質問を参照してください。

于 2013-10-17T14:48:49.513 に答える
1

私の考え

短所は何ですか:

  • DAL で定義した静的メソッドを使用する場所では、単体テストを実際に行うことはできません。
  • また、それらは強く結合されているため、実行時にスワップアウトすることが要件になった場合、それらをより困難にします。
  • トランザクションで複数の更新をコミットする必要がある場合、さらに複雑になる可能性があります

呼び出しごとに新しい DbContext を作成するのは間違っていますか?

  • いいえ、これで問題ありません。DbContext は軽量であり、この方法で使用することを意図しています。

その他のパタ​​ーン

  • 特に作業単位パターンで使用する場合は、かなり堅実なリポジトリ パターンについて既に言及しました。

Linqtosql を使用しますか

  • いいえ - Linqtosql はほぼ完了しています。エンティティ フレームワークは、この問題に対してより完全で一般的に優れたソリューションを提供します。
于 2013-10-17T14:21:03.503 に答える
0

実装方法を再考しますGetUsers()ToList()基になるテーブルのすべての行が返され、メモリに格納されるように呼び出しています。テーブルが十分に大きくなると、パフォーマンスの問題が発生します。IQueryable<User>代わりにを返し、メソッドを持っている方が良いreturn context.Usersです。

もちろん、 を実行するまでにコンテキストが破棄されているという問題が発生するため、IQueryable<>コンテキストのライフサイクルを別の方法で処理する必要があります。

プロジェクトが十分に小さい場合は、Context のインスタンスをコントローラー レベルで格納し、コントローラーが破棄されるときに破棄することができます。Userこれを行う場合は、追加のクエリが実行される原因となる (たとえば、コレクションが存在する場合にコレクションにアクセスする) か、エラーが発生するようなことをビューで行わないようにしてください。

于 2013-10-17T14:31:40.343 に答える