本文介绍了MVC3 EF工作单元+通用存储库+ Ninject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是MVC3的新手,并且一直在关注asp.net网站上的出色教程.但是,我不太了解如何在Ninject中使用工作单元和通用存储库模式.我以本教程为起点: http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/在ASP.NET MVC应用程序中实现存储库和工作单元模式

I'm new to MVC3 and have been following the awesome tutorials on the asp.net website. However, I can't quite wrap my head around how to use Unit of Work and Generic Repository patterns with Ninject. I used this tutorial as a starting point: 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

无需使用接口,我知道可以像这样实现它:

Without using interfaces, I know I can implement it like so:

通用存储库:

public class GenericRepository<TEntity> : IGenericRepository<TEntity>
                                          where TEntity : class
{
    internal MyContext context;
    internal DbSet<TEntity> dbSet;

    public GenericRepository(MyContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }
}

工作单元:

private MyContext context = new MyContext();
private GenericRepository<Student> studentRepository;
private GenericRepository<Course> courseRepository;

public GenericRepository<Student> StudentRepository
{
    if (this.studentRepository == null)
    {
        this.studentRepository = new GenericRepository<Student>(context);
    }
    return studentRepository;
}

public GenericRepository<Course> CourseRepository
{
    if (this.courseRepository == null)
    {
        this.courseRepository = new GenericRepository<Course>(context);
    }
    return courseRepository;
}

此设置使我可以将相同的上下文传递给所有存储库,然后调用单个Save()函数来提交更改.

This setup allows me to pass the same context to all repositories, and then call a single Save() function to commit the changes.

我知道我可以使用接口IGenericRepository<TEntity>和具体实现GenericRepository<TEntity>,然后使用Ninject绑定它们:

I know I can use an interface IGenericRepository<TEntity> and the concrete implementation GenericRepository<TEntity> and then bind them using Ninject:

kernel.Bind(typeof(IGenericRepository<>)).To(typeof(GenericRepository<>));

但是我将如何设置我的IUnitOfWorkUnitOfWork以确保我的所有存储库共享一个数据库上下文?我是否一开始就做对了?我进行了搜索,但似乎只找到了只使用通用存储库而没有工作单元的教程.

But how would I go about setting up my IUnitOfWork and UnitOfWork to ensure that all my repositories share a single database context? Am I even doing it right in the first place? I've searched around but all I seem to find are tutorials that only use generic repositories without a unit of work.

推荐答案

您的基本存储库:

public class BaseRepository<TObject> : IRepository<TObject>
     where TObject : class
{

    public BaseRepository(IUnitOfWork unitOfWork)
    {
        if (unitOfWork == null) throw new ArgumentException("unitOfWork");
        UnitOfWork = unitOfWork;
    }

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

    public void Dispose()
    {
        if (sharedContext && (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<Key>(Expression<Func<TObject, Key>> sortingSelector, Expression<Func<TObject, bool>> filter, out int total,
        SortingOrders sortby = SortingOrders.Asc, int index = 0, int size = 50)
    {
        int skipCount = index * size;
        var _resultSet = filter != null ? DbSet.Where(filter).AsQueryable() : DbSet.AsQueryable();
        total = _resultSet.Count();

        _resultSet = sortby == SortingOrders.Asc ? _resultSet.OrderBy(sortingSelector).AsQueryable() : _resultSet.OrderByDescending(sortingSelector).AsQueryable();
        _resultSet = skipCount == 0 ? _resultSet.Take(size) : _resultSet.Skip(skipCount).Take(size);
        return _resultSet;
    }

    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, bool SaveChanges = true)
    {
        var newEntry = DbSet.Add(TObject);
        if (!sharedContext && SaveChanges)
            Context.SaveChanges();
        return newEntry;
    }

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

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

    public virtual int Update(TObject TObject, bool SaveChanges = true)
    {
        var entry = Context.Entry(TObject);
        DbSet.Attach(TObject);
        entry.State = EntityState.Modified;
        if (!sharedContext && SaveChanges)
            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 (!sharedContext)
            return Context.SaveChanges();
        return 0;
    }

    /// <summary>
    /// Sets the state of an entity.
    /// </summary>
    /// <param name="entity">object to set state.</param>
    /// <param name="entityState"><see cref="EntityState"/></param>
    protected virtual void SetEntityState(object entity, EntityState entityState)
    {
        Context.Entry(entity).State = entityState;
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="entity"></param>
    protected virtual void Attach(object entity)
    {
        if (Context.Entry(entity).State == EntityState.Detached)
            Context.Entry(entity).State = EntityState.Modified;
    }


    protected virtual void Detach(object entity)
    {
        Context.Entry(entity).State = EntityState.Detached;
    }

    public void SubmitChanges()
    {
        UnitOfWork.SaveChanges();
    }


    #region Properties

    private bool sharedContext { get; set; }

    /// <summary>
    /// Unit of work controlling this repository.
    /// </summary>
    protected IUnitOfWork UnitOfWork { get; set; }

    /// <summary>
    /// Provides access to the ef context we are working with
    /// </summary>
    internal IMyContext Context
    {
        get
        {
            return (IMyContext)UnitOfWork;
        }
    }

    #endregion
}

Notice Context是实现UnitOfWork的接口.

Notice Context is an interface implementing UnitOfWork.

您的上下文界面:

public interface IMyContext : IDbContext
{
    DbSet<Sometype> SomeProperty { get; set; }
    ...

}

您的IDbContext接口:

Your IDbContext interface:

 public interface IDbContext
{
    DbChangeTracker ChangeTracker { get; }
    DbContextConfiguration Configuration { get; }
    Database Database { get; }

    void Dispose();
    void Dispose(bool disposing);
    DbEntityEntry Entry(object entity);
    DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
    bool Equals(object obj);
    int GetHashCode();
    Type GetType();
    IEnumerable<DbEntityValidationResult> GetValidationErrors();
    void OnModelCreating(DbModelBuilder modelBuilder);
    int SaveChanges();
    DbSet<TEntity> Set<TEntity>() where TEntity : class;
    DbSet Set(Type entityType);
    bool ShouldValidateEntity(DbEntityEntry entityEntry);
    string ToString();
    DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items);
}

然后是实际的上下文实现:

Then the actual context implementation:

 public class MyContext : DbContext, IUnitOfWork, IMyContext
{
    //public MyContext()
    //{
    //    Database.SetInitializer<ReconContext>(null);
    //}

    public ReconContext()
        : base("Name=ReconContext")
    {
        ((IObjectContextAdapter)this).ObjectContext.ContextOptions.ProxyCreationEnabled = false;
    }

    public DbSet<SomeType> SomeProperty { get; set; }
    ....



    public new void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new SomePropertyMap());
        .....
        base.OnModelCreating(modelBuilder);
    }

    int IUnitOfWork.SaveChanges()
    {
        return base.SaveChanges();
    }

    void IDisposable.Dispose()
    {
        base.Dispose();
    }

    public new void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }

    public new bool ShouldValidateEntity(DbEntityEntry entityEntry)
    {
        return base.ShouldValidateEntity(entityEntry);
    }

    public new DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
    {
        return base.ValidateEntity(entityEntry, items);
    }



}

然后在您的ninject配置中只需执行以下操作:

Then in your ninject config you simply do:

kernel.Bind<IUnitOfWork<MyContext>>().To<MyContext>().InRequestScope();

这篇关于MVC3 EF工作单元+通用存储库+ Ninject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 22:06