泛型Repository的使用
以前一直用业务模型跟Repository一对一的形式,但是看到很多开源项目中都是使用泛型的Repository,觉得会简便一些,但是也存在一些问题。
比如member表是不应该有删除接口的, 如果使用泛型的repository的话,delete方法会入侵member类。不过不管怎么说,使用泛型的仓储会减少很多代码量和重复工作。
1、建立实体类(这是一个任务计划的类,下一篇还要讲怎么在mvc中写计划任务,比如要过24小时自动清理一下缓存,比如跟国际金融相关的,要24小时获取一次汇率等等):
public class ScheduleTask {
/// <summary>
/// 主键ID
/// </summary>
public int ID { get; set; }
/// <summary>
/// 任务名字
/// </summary>
public string Name { get; set; }
/// <summary>
/// 运行周期(秒)
/// </summary>
public int Seconds { get; set; }
/// <summary>
/// 相应的ITask类的类型
/// </summary>
public string Type { get; set; }
/// <summary>
/// 任务是否启用
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// 遇到错误是否停止
/// </summary>
public bool StopOnError { get; set; }
/// <summary>
/// 最后开始时间
/// </summary>
public DateTime? LastStartDate { get; set; }
/// <summary>
/// 最后结束时间
/// </summary>
public DateTime? LastEndDate { get; set; }
/// <summary>
/// 最后执行成功时间
/// </summary>
public DateTime? LastSuccessDate { get; set; }
}
2、创建DbContext:
public class HelperDbContext : DbContext {
public HelperDbContext()
: base("TbsContext") {
}
public DbSet<ScheduleTask> ScheduleTasks { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Configurations.Add(new ScheduleTaskMap());
base.OnModelCreating(modelBuilder);
}
}
解释一下,base("TbsContext") 是读取webconfig里面名为TbsContext的数据库链接字符串,如果不写,应该是默认读取HelperDbContext
3、重点来了:IRepository接口
public partial interface IRepository<T> where T : class
{
T GetById(object id);
void SaveChanges();
void Insert(T entity);
void Update(T entity);
void Delete(T entity);
IQueryable<T> Table { get; }
IQueryable<T> TableNoTracking { get; }
}
4、实现:
public partial class EFRepository<T> : IRepository<T> where T : class {
private HelperDbContext _context = new HelperDbContext();
private IDbSet<T> _entities;
/// <summary>
/// Entities
/// </summary>
protected virtual IDbSet<T> Entities {
get {
if (_entities == null)
_entities = _context.Set<T>();
return _entities;
}
}
public T GetById(object id) {
return this.Entities.Find(id);
}
public void SaveChanges() {
this._context.SaveChanges();
}
public void Insert(T entity) {
try {
if (entity == null)
throw new ArgumentNullException("entity");
this.Entities.Add(entity);
this._context.SaveChanges();
}
catch (DbEntityValidationException dbEx) {
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;
var fail = new Exception(msg, dbEx);
//Debug.WriteLine(fail.Message, fail);
throw fail;
}
}
public void Update(T entity) {
try {
if (entity == null)
throw new ArgumentNullException("entity");
this._context.SaveChanges();
}
catch (DbEntityValidationException dbEx) {
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
var fail = new Exception(msg, dbEx);
//Debug.WriteLine(fail.Message, fail);
throw fail;
}
}
public void Delete(T entity) {
try {
if (entity == null)
throw new ArgumentNullException("entity");
this.Entities.Remove(entity);
this._context.SaveChanges();
}
catch (DbEntityValidationException dbEx) {
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
var fail = new Exception(msg, dbEx);
//Debug.WriteLine(fail.Message, fail);
throw fail;
}
}
public IQueryable<T> Table {
get {
return this.Entities;
}
}
public IQueryable<T> TableNoTracking {
get {
return this.Entities.AsNoTracking();
}
}
}
5、在IOC中注册一下,不注册的话就用常规的接口实现的写法就可以了,栗子中是ninject
ninjectKernel.Bind(typeof(IRepository<>)).To(typeof(EFRepository<>));
6、使用案例:
private readonly IRepository<ScheduleTask> _repo;
public HomeController(IRepository<ScheduleTask> repo) {
this._repo = repo;
}
public ActionResult Index() {
var aa = _repo.Table.SingleOrDefault();
return Content(aa.Name);
}
* 说明一下,最好不要在controller中直接调用数据访问层,应该建一个service层,然后service暴露操作crud

浙公网安备 33010602011771号