在我的ASP.NET MVC 4项目中,我仔细遵循了这个实现Repository和Unit Of Work的例子中的设计原则。
我对这篇文章特别感兴趣,该文章是在显示Generic Repository之后编写的:
此通用存储库将处理典型的CRUD要求。当特定实体类型具有特殊要求(例如更复杂的过滤或排序)时,您可以创建具有该类型的其他方法的派生类。
由于我的应用符合特定情况,我尝试这样做。我创建了一个GenericRepository,就像文章中的那个,以及一个SharedContext类(SharedContext正是文章中的UnitOfWork类,但这个名字对我来说更有意义)
GenericRepository:
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(我不再使用)了,而且我暴露了上下文。
THX,
编辑:
我需要公开SharedContext中的Context属性,因为如果我删除了GenericRepository中的构造函数(需要一个SharedContext)和CustomerRepository类中的:base(ctx),我得到这个:
BusinessLogicLayer.DBModel.Customer不包含带0个参数的构造函数
答案 0 :(得分:1)
创建专门的客户存储库是正确的做法。我建议您更新SharedContext
类,以便CustomerRepository
属性返回CustomerRepository
类的实例,而不是GenericRepository<Cutomer>
。
这样,当您从CustomerRepository
访问SharedContext
属性时,您将拥有通用存储库的方法以及CustomerRepository
类的专用方法。< / p>
答案 1 :(得分: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;
}
}
}