Asp.net-Mvc-2

Entity Framework 4 CTP 4 / CTP 5 通用儲存庫模式和單元可測試

  • December 14, 2010

我正在使用最新的 Entity Framework CTP 5 版本並建構一個簡單的 asp.net MVC 部落格,其中只有兩個表:Post 和 Comments。這完全在 POCO 中完成,我只需要 DbContext 部分的幫助,我需要它可以進行單元測試(使用 IDbSet?),並且我需要一個簡單/通用的儲存庫模式來添加、更新、刪除、檢索。任何幫助表示讚賞。

謝謝。

從你的 DbContext 開始,創建一個名為 Database.cs 的新文件:

數據庫.cs

public class Database : DbContext
   {

       private IDbSet<Post> _posts;

       public IDbSet<Post> Posts {
           get { return _posts ?? (_posts = DbSet<Post>()); }
       }

       public virtual IDbSet<T> DbSet<T>() where T : class {
           return Set<T>();
       }
       public virtual void Commit() {
           base.SaveChanges();
       }
}

定義一個 IDatabaseFactory 並用 DatabaseFactory 實現它:

IDatabaseFactory.cs

public interface IDatabaseFactory : IDisposable
   {
       Database Get();
   }

數據庫工廠.cs

public class DatabaseFactory : Disposable, IDatabaseFactory {
       private Database _database;
       public Database Get() {
           return _database ?? (_database = new Database());
       }
       protected override void DisposeCore() {
           if (_database != null)
               _database.Dispose();
       }
   }

一次性擴展方法:

一次性用品.cs

public class Disposable : IDisposable
   {
       private bool isDisposed;

       ~Disposable()
       {
           Dispose(false);
       }

       public void Dispose()
       {
           Dispose(true);
           GC.SuppressFinalize(this);
       }
       private void Dispose(bool disposing)
       {
           if(!isDisposed && disposing)
           {
               DisposeCore();
           }

           isDisposed = true;
       }

       protected virtual void DisposeCore()
       {
       }
   }

現在我們可以定義我們的 IRepository 和 RepositoryBase

IRepository.cs

public interface IRepository<T> where T : class
{
   void Add(T entity);
   void Delete(T entity);
   void Update(T entity);
   T GetById(long Id);
   IEnumerable<T> All();
   IEnumerable<T> AllReadOnly();
}

RepositoryBase.cs

public abstract class RepositoryBase<T> where T : class
   {
       private Database _database;
       private readonly IDbSet<T> _dbset;
       protected RepositoryBase(IDatabaseFactory databaseFactory)
       {
           DatabaseFactory = databaseFactory;
           _dbset = Database.Set<T>();
       }

       protected IDatabaseFactory DatabaseFactory
       {
           get; private set;
       }

       protected Database Database
       {
           get { return _database ?? (_database = DatabaseFactory.Get()); }
       }
       public virtual void Add(T entity)
       {
           _dbset.Add(entity);
       }

       public virtual void Delete(T entity)
       {
           _dbset.Remove(entity);
       }

       public virtual void Update(T entity)
       {
           _database.Entry(entity).State = EntityState.Modified;
       }
       public virtual T GetById(long id)
       {
           return _dbset.Find(id);
       }

       public virtual IEnumerable<T> All()
       {
           return _dbset.ToList();
       }
       public virtual IEnumerable<T> AllReadOnly()
       {
           return _dbset.AsNoTracking().ToList();
       }
   }

現在您可以創建您的 IPostRepository 和 PostRepository:

IPostRepository.cs

    public interface IPostRepository : IRepository<Post>
       {
           //Add custom methods here if needed
           Post ByTitle(string title);
       }

PostRepository.cs

   public class PostRepository : RepositoryBase<Post>, IPostRepository
       {
           public PostRepository(IDatabaseFactory databaseFactory) : base(databaseFactory)
           {
           }
           public Post ByTitle(string title) {
               return base.Database.Posts.Single(x => x.Title == title);
           }
       }

最後,UoW:

IUnitOfWork.cs

public interface IUnitOfWork
{
   void Commit();
}

UnitOfWork.cs

private readonly IDatabaseFactory _databaseFactory;
private Database _database;

public UnitOfWork(IDatabaseFactory databaseFactory)
{
   _databaseFactory = databaseFactory;
}

protected Database Database
{
   get { return _database ?? (_database = _databaseFactory.Get()); }
}

public void Commit()
{
   Database.Commit();
}

在您的控制器中使用:

private readonly IPostRepository _postRepository;
private readonly IUnitOfWork_unitOfWork;

       public PostController(IPostRepository postRepository, IUnitOfWork unitOfWork)
       {
           _postRepository = postRepository;
           _unitOfWork = unitOfWork;
       }

       public ActionResult Add(Post post) {
           _postRepository.Add(post);
           _unitOfWork.Commit();
       }

您將需要使用像 StructureMap 這樣的 IoC 容器來完成這項工作。您可以通過 NuGet 安裝結構映射,或者如果您使用的是 MVC 3,則可以安裝 StructureMap-MVC NuGet 包。(以下連結)

安裝包 StructureMap.MVC4

安裝包 StructureMap.MVC3

安裝包結構圖

如果您有任何問題,請告訴我。希望能幫助到你。

引用自:https://stackoverflow.com/questions/4442828