1

私の ASP.NET MVC 4 プロジェクトでは、Repository と Unit Of Work を実装するこの例の設計原則に注意深く従っています。

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net- mvc-アプリケーション

私は、汎用リポジトリを示した後に書かれた記事に関する次のコメントに特に興味があります。

この汎用リポジトリは、典型的な CRUD 要件を処理します。より複雑なフィルタリングや順序付けなど、特定のエンティティ タイプに特別な要件がある場合は、そのタイプの追加メソッドを持つ派生クラスを作成できます。

私のアプリはその特定のケースを満たしているので、これをやろうとしました。記事と同じように GenericRepository と SharedContext クラスを作成しました (SharedContext は記事の UnitOfWork クラスとまったく同じですが、この名前の方が私にはわかりやすいです)。

汎用リポジトリ:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace BusinessLogicLayer.Repositories
{
public class GenericRepository<T> where T: class
{
    internal DbSet<T> _dbSet;
    internal DBConnection _context;

    #region constructors

    public GenericRepository(SharedContext ctx)
    {
        _context = ctx.Context;
    }

    public GenericRepository(DBConnection context)
    {
        _context = context;
        _dbSet = context.Set<T>();
    }
    #endregion

}
}

SharedContext (作業単位) クラス:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BusinessLogicLayer.Repositories
{
public class SharedContext : IDisposable
{
    #region repositories
    private GenericRepository<Entities.Customer> _customerRepository;
    /// <summary>
    /// access the Customer entity
    /// </summary>
    public GenericRepository<Entities.Customer> CustomerRepository
    {
        get 
        {
            if (_customerRepository == null)
                _customerRepository = new GenericRepository<Entities.Customer>(_context);

            return _customerRepository;
        }
    }
    #endregion
    
    #region context management 
    
    private Entities.DBConnection _context = new Entities.DBConnection();
    internal Entities.DBConnection Context { get { return _context; } }
    //other methods - save, delete
    #endregion
}
}

ここに問題があります。上記の Context プロパティをどのように公開したかに注意してください。これが実際に意図されているかどうかは疑問です。それを行うことでパターンを壊しているように感じます。すべてが同じコンテキストでリポジトリを介して制御されるという考えが非常に気に入っていますが、汎用リポジトリでは提供されていないメソッドがいくつか必要なので、別の CustomerRepository を作成しました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace BusinessLogicLayer.Repositories 
{
public class CustomerRepository: GenericRepository<Entities.Customer>
{
    public CustomerRepository(SharedContext ctx)
        : base(ctx)
    {  }
    
    public decimal GetCustomerBonusByFrequency()
    {
        //
        
    }
}
}

...私のコントローラークラスでは、次のように使用します。

private SharedContext ctx = new SharedContext();

public PartialViewResult CustomerBonus()
{
   CustomerRepository cRepo = new CustomerRepository(ctx);
   var bonus = cRepo.GetCustomerBonusByFrequency();
   return PartialView(bonus);
}

だから私の2つの質問は次のとおりです。

  • リスト項目

    これは、記事で言及されている追加機能を追加するための意図された方法ですか? クラス CustomRepository を参照しています。これは、GenericRepository (もう使用していない) を介して Customer を取得する方法が既に存在していたため、パターンが壊れているように感じます。さらに、コンテキストを公開しています。

  • これが悪い場合、どうすれば正しく行うことができますか? 必要なのは、Customer エンティティに追加のメソッドを用意することだけですが、パターンを尊重する方法で行います。

どうも、

編集:

GenericRepository (SharedContext を受け取る) のコンストラクターと CustomerRepository クラスの :base(ctx) を削除すると、次のようになるため、SharedContext で Context プロパティを公開する必要がありました。

BusinessLogicLayer.DBModel.Customer には、0 引数を取るコンストラクターが含まれていません

4

2 に答える 2

1
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data;

namespace Demo.DAL
{
    public class Repository<TObject>

        where TObject : class
    {
        protected DB Context;
        protected DB Context = null;
        private bool shareContext = false;

        public Repository()
        {
            Context = new DB();
        }

        public Repository(DB context)
        {
            Context = context;
            shareContext = true;
        }

        protected DbSet<TObject> DbSet
        {
            get
            {
                return Context.Set<TObject>();
            }
        }

        public void Dispose()
        {
            if (shareContext && (Context != null))
                Context.Dispose();
        }

        public virtual IQueryable<TObject> All()
        {
            return DbSet.AsQueryable();
        }

        public virtual IQueryable<TObject> 
        Filter(Expression<Func<TObject, bool>> predicate)
        {
            return DbSet.Where(predicate).AsQueryable<TObject>();
        }

        public virtual IQueryable<TObject> Filter(Expression<Func<TObject, bool>> filter,
         out int total, int index = 0, int size = 50)
        {
            int skipCount = index * size;
            var _resetSet = filter != null ? DbSet.Where(filter).AsQueryable() : 
                DbSet.AsQueryable();
            _resetSet = skipCount == 0 ? _resetSet.Take(size) : 
                _resetSet.Skip(skipCount).Take(size);
            total = _resetSet.Count();
            return _resetSet.AsQueryable();
        }

        public bool Contains(Expression<Func<TObject, bool>> predicate)
        {
            return DbSet.Count(predicate) > 0;
        }

        public virtual TObject Find(params object[] keys)
        {
            return DbSet.Find(keys);
        }

        public virtual TObject Find(Expression<Func<TObject, bool>> predicate)
        {
            return DbSet.FirstOrDefault(predicate);
        }

        public virtual TObject Create(TObject TObject)
        {
            var newEntry = DbSet.Add(TObject);
            if (!shareContext)
                Context.SaveChanges();
            return newEntry;
        }

        public virtual int Count
        {
            get
            {
                return DbSet.Count();
            }
        }

        public virtual int Delete(TObject TObject)
        {
            DbSet.Remove(TObject);
            if (!shareContext)
                return Context.SaveChanges();
            return 0;
        }

        public virtual int Update(TObject TObject)
        {
            var entry = Context.Entry(TObject);
            DbSet.Attach(TObject);
            entry.State = EntityState.Modified;
            if (!shareContext)
                return Context.SaveChanges();
            return 0;
        }

        public virtual int Delete(Expression<Func<TObject, bool>> predicate)
        {
            var objects = Filter(predicate);
            foreach (var obj in objects)
                DbSet.Remove(obj);
            if (!shareContext)
                return Context.SaveChanges();
            return 0;
        }
    }
} 
于 2013-01-10T11:23:41.833 に答える
1

専用の顧客リポジトリを作成することは正しいことです。プロパティがクラスのインスタンスではなくクラスのインスタンスを返すSharedContextように、クラスを更新することをお勧めします。CustomerRepositoryCustomerRepositoryGenericRepository<Cutomer>

CustomerRepositoryこのようにして、 からプロパティにアクセスするSharedContextと、汎用リポジトリのメソッドだけでなく、CustomerRepositoryクラスの特殊なメソッドも利用できるようになります。

于 2012-11-26T23:22:59.157 に答える