MVC小型商务网站实例(3)--Repository模式
Repository翻译为资源库, 通过用来访问领域对象的一个类似集合的接口,在领域与数据映射层之间进行协调。使用该模式可以将领域模型从客户代码和数据映射层之间解耦出来。
首先我们将数据操作的相同部份抽象出一个接口IRepository<T>,然后让各实体操作类实现此接口,代码:
public interface IRepository<T>
{
void Add(T entity);
void Del(T entity);
void Del(ICriteria criteria);
void Update(int entityId, T entity);
T Find(int entityId);
IList<T> Find(ICriteria criteria);
IList<T> FindAll();
IList<T> Find(ICriteria criteria, int pageIndex, int pageSize, Order orderExpr);
IQueryable<T> FindQueryable(ICriteria criteria, int page, int pageSize, Order orderExpr);
int Count(ICriteria criteria);
void SaveChanges();
void AcceptAllChanges();
}
然后实现这个公共操作类BaseRepositoryBase<T>:
/// <summary>
/// 数ºy据Y仓?储ä¡é基¨´类¤¨¤
/// </summary>
/// <typeparam name="T">EF数ºy据Y类¤¨¤</typeparam>
public abstract class BaseRepositoryBase<T> : IRepository<T> where T : class
{
protected SouthShopEntities1 dataContext;
private string _entitiesSetName;
public BaseRepositoryBase()
{
this.dataContext = BaseRepository.CreateDataContext();
}
public BaseRepositoryBase(bool defaultEntitySetName)
{
this.dataContext = BaseRepository.CreateDataContext();
if (defaultEntitySetName)
{
if (EntitySetName.EndsWith("y"))
{
this._entitiesSetName = StringExtensions.RemoveChars(EntitySetName, EntitySetName.Length - 1) + "ies";
}
else
{
this._entitiesSetName = EntitySetName + "s";
}
}
else
{
throw new ArgumentNullException("entitiesSet");
}
}
public BaseRepositoryBase(SouthShopEntities1 dataContext, string entitiesSetName)
{
if (dataContext == null)
throw new ArgumentNullException("DataContext");
if (String.IsNullOrEmpty(entitiesSetName))
throw new ArgumentNullException("entitiesSet");
this.dataContext = dataContext;
this._entitiesSetName = entitiesSetName;
}
/// <summary>
/// 实º¦Ì体¬?类¤¨¤名?称?
/// </summary>
protected string EntitySetName
{
get { return typeof(T).Name; }
}
/// <summary>
/// 实º¦Ì体¬?集¡¥名?称?
/// </summary>
protected string EntitiesSetName
{
get { return _entitiesSetName; }
set { _entitiesSetName = value; }
}
/// <summary>
/// 实º¦Ì体¬?集¡¥对?象¨®
/// </summary>
protected ObjectQuery<T> EntitySet
{
get { return dataContext.CreateQuery<T>("[" + EntitiesSetName + "]"); }
}
#region IRepository<T> 成¨¦员¡À
public virtual void Add(T entity)
{
dataContext.AddObject(EntitiesSetName, entity);
}
public virtual void Del(T entity)
{
dataContext.DeleteObject(entity);
}
public virtual void Del(ICriteria criteria)
{
IEnumerable<T> query = EntitySet.Where(criteria.Expression, criteria.Parameters.Select(p => new ObjectParameter(p.Name, p.Value)).ToArray());
foreach (var item in query)
{
dataContext.DeleteObject(item);
}
dataContext.SaveChanges();
}
public virtual void Update(int entityId, T entity)
{
T t = Find(entityId);
t = entity;
dataContext.ApplyPropertyChanges(EntitiesSetName, t);
}
public IList<T> Find(ICriteria criteria)
{
if (criteria == null)
throw new ArgumentNullException("criteria");
var query = EntitySet.Where(criteria.Expression, criteria.Parameters.Select(p => new ObjectParameter(p.Name, p.Value)).ToArray());
//var str = query.ToTraceString();
return ToList(query);
}
public IList<T> FindAll()
{
return ToList(EntitySet);
}
public IList<T> Find(ICriteria criteria, int page, int pageSize, Order orderExpr)
{
if (criteria == null || orderExpr == null)
throw new ArgumentNullException("criteria");
var query = EntitySet.Where(criteria.Expression, criteria.Parameters.Select(p => new ObjectParameter(p.Name, p.Value)).ToArray());
return ToList(orderExpr.OrderFrom<T>(query).Skip((page - 1) * pageSize).Take(pageSize));
}
public IQueryable<T> FindQueryable(ICriteria criteria, int page, int pageSize, Order orderExpr)
{
if (criteria == null || orderExpr == null)
throw new ArgumentNullException("criteria");
var query = EntitySet.Where(criteria.Expression, criteria.Parameters.Select(p => new ObjectParameter(p.Name, p.Value)).ToArray());
return orderExpr.OrderFrom<T>(query).Skip((page - 1) * pageSize).Take(pageSize);
}
public int Count(ICriteria criteria)
{
if (criteria == null)
throw new ArgumentNullException("criteria");
return EntitySet.Where(criteria.Expression, criteria.Parameters.Select(p => new ObjectParameter(p.Name, p.Value)).ToArray()).Count();
}
public void SaveChanges()
{
dataContext.SaveChanges();
}
public void AcceptAllChanges()
{
dataContext.AcceptAllChanges();
}
public virtual T Find(int entityId)
{
return Find(new EqualParameterCriteria(EntitySetName + "Id", entityId)).FirstOrDefault();
}
protected virtual IList<T> ToList(IQueryable<T> query)
{
try
{
return query.AsEnumerable().Select(c => c).Cast<T>().ToList();
}
catch (Exception ex)
{
throw new ApplicationException(ex.Message);
}
}
#endregion
}
接下来各表的业务处理再单独定义另外一个接口,让它继承 IRepository<T> 如:
public interface IProductRepository<T>:IRepository<T> where T :class
{
void Del(IEnumerable<int> values);
int GetProductId(string productName);
IEnumerable<ProductList> GetCategoryHotSell(int categoryId);
}
这样做的目的是项目采用了IOC容器(Castle Windsor)进行解耦,还可以实现一些非公共业务处理。
最后该实体的Repository类实现如下:
public class ProductRepository: BaseRepositoryBase<Product>, IProductRepository<Product>
{
public ProductRepository()
{
this.EntitiesSetName = "Products";
}
public void Del(IEnumerable<int> values)
{
var query = this.EntitySet.Where(ContainsCriteria.ContainsExpression<Product, int>(c => c.ProductId, values)).ToList();
foreach (var value in query)
{
this.dataContext.DeleteObject(value);
}
this.SaveChanges();
}
public int GetProductId(string productName)
{
var query = from p in this.EntitySet
where p.ProductName == productName
select p.ProductId;
return query.FirstOrDefault();
}
public IEnumerable<ProductList> GetCategoryHotSell(int categoryId)
{
var query = (from p in this.EntitySet
where p.CategoryId == categoryId
orderby p.SellAmount descending
select new ProductList
{
CategoryId = categoryId,
ProductId = p.ProductId,
ProductName = p.ProductName
}).Take(10).ToList();
return query;
}
}
这样我们就实现了Repository模式。