【问题标题】:Customising an implementation of Repository and Unit Of Work自定义存储库和工作单元的实现
【发布时间】:2012-11-26 22:21:35
【问题描述】:

在我的 ASP.NET MVC 4 项目中,我仔细遵循了这个实现存储库和工作单元示例中的设计原则。

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-application

我对这篇文章的评论特别感兴趣,是在展示了通用存储库之后写的:

这个通用存储库将处理典型的 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);
}

所以我的两个问题是:

  • 列表项

    这是文章中提到的添加额外功能的预期方式吗?我指的是 CustomRepository 类,这对我来说感觉像是一种模式的破坏,因为已经有一种方法可以让客户通过 GenericRepository(我不再使用),而且我正在公开上下文。

  • 如果这很糟糕,那么我应该如何正确地做到这一点?我只需要为我的客户实体提供额外的方法,但要以尊重模式的方式。

谢谢,

编辑:

我需要在 SharedContext 中公开 Context 属性,因为如果我删除 GenericRepository 中的构造函数(采用 SharedContext)和 CustomerRepository 类中的 :base(ctx),我会得到:

BusinessLogicLayer.DBModel.Customer 不包含采用 0 个参数的构造函数

【问题讨论】:

    标签: c# entity-framework c#-4.0 repository-pattern unit-of-work


    【解决方案1】:

    创建一个专门的客户存储库是正确的做法。我建议应该更新您的 SharedContext 类,以便 CustomerRepository 属性返回 CustomerRepository 类的实例,而不是 GenericRepository&lt;Cutomer&gt; 的实例。

    这样,当您从SharedContext 访问CustomerRepository 属性时,您将可以使用通用存储库的方法以及您的CustomerRepository 类的专用方法。

    【讨论】:

    • 是的,当然,就是这样!这很有意义。共享上下文通过通用存储库或通过特殊类路由实体。完美运行,谢谢。
    【解决方案2】:
    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;
            }
        }
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-02
      相关资源
      最近更新 更多