0

我的应用程序中有以下层。

  1. Repository.Ef(这个处理 ef 的上下文)
  2. 实体(这里是 ef 的所有实体)
  3. 核心(这一层处理所有业务,就像 Ef <> Gui 之间的包装器一样工作)
  4. Gui(这是用户界面)

我有大多数类的接口并使用 DI,但是这个版本被压缩为只显示类。

这是 UnitOfWork,它在我的 Repository.Ef 层中保存 DbContext。

public class UnitOfWork : DbContext, IUnitOfWork
    {
        static UnitOfWork()
        {
            Database.SetInitializer<UnitOfWork>(null);
        }

        public UnitOfWork()
            : base("Name=SalesDb") 
        {
        }

        public IRepository<T> Repository<T>() where T : EntityBase
        {
            return new Repository<T>(Set<T>());
        }

        public void ApplyStateChanges()
        {
            foreach (var dbEntityEntry in ChangeTracker.Entries())
            {
                var entityState = dbEntityEntry.Entity as EntityBase;
                if (entityState == null)
                    throw new InvalidCastException("All entites must implement the IObjectState interface, " +
                                                   "this interface must be implemented so each entites state can explicitely determined when updating graphs.");

                dbEntityEntry.State = StateHelper.ConvertState(entityState.State);
            }
        }

        #region DBSET

    // HERE IS ALL MY DBSETS

        #endregion

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }

        public override int SaveChanges()
        {
            ApplyStateChanges();
            return base.SaveChanges();
        }
    }

这是我的存储库(与 UnitOfWork 相同的层)

    public class Repository<T> : IRepository<T> where T : class, IEntity
{
    private readonly DbSet<T> _dbSet;

    public Repository(DbSet<T> dbSet)
    {
        _dbSet = dbSet;
    }

    public IQueryable<T> Query()
    {
        var data = _dbSet.AsQueryable();
        return data;
    }

    public IEnumerable<T> GetAll()
    {
        return _dbSet;
    }

    public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
    {
        return _dbSet.Where(predicate);
    }

    public T FindById(int id)
    {
        return _dbSet.Find(id);
    }

    public void Add(T entity)
    {
        entity.State = ObjectState.Added;
        _dbSet.Add(entity);
    }

    public void Remove(T entity)
    {
        entity.State = ObjectState.Deleted;
        _dbSet.Remove(entity);
    }

    public void Update(T entity)
    {
        entity.State = ObjectState.Modified;
        _dbSet.Attach(entity);
    }
}

这是我的核心层(业务规则和 GUI 层之间的包装) 以下是我的 ServiceUnit。

  public class ServiceUnit
{
    internal readonly IUnitOfWork unitOfWork;

    public ServiceUnit()
    {
        unitOfWork = new UnitOfWork();
    }

    public void Add<T>(T entity, int marketId, string username) where T : EntityBase
    {
        entity.MarketId = marketId;
        entity.ChUser = username;
        entity.ChTime = DateTime.Now;
        entity.Deleted = false;

        unitOfWork.Repository<T>().Add(entity);
        unitOfWork.SaveChanges();
    }

    public void Update<T>(T entity, string username) where T : EntityBase
    {
        entity.ChUser = username;
        entity.ChTime = DateTime.Now;

        unitOfWork.Repository<T>().Update(entity);
        unitOfWork.SaveChanges();
    }

    public void Remove<T>(int id) where T : EntityBase
    {
        var entity = unitOfWork.Repository<T>().FindById(id);
        entity.Deleted = true;
        entity.ChTime = DateTime.Now;

        unitOfWork.Repository<T>().Update(entity);
        unitOfWork.SaveChanges();
    }

    public IEnumerable<T> Find<T>(int? marketId = null, Expression<Func<T, bool>> predicate = null) where T : EntityBase
    {
        var data = unitOfWork.Repository<T>()
            .Find(predicate);

        if (marketId != null)
        {
            data = data
                .Where(t => t.MarketId == marketId);
        }

        return data;
    }

    public T FindById<T>(int id) where T : EntityBase
    {
        return unitOfWork.Repository<T>().FindById(id);
    }

    public void Commit()
    {
        unitOfWork.SaveChanges();
    }

}

这是一个处理所有联系功能的服务类

    public class ContactService
{
    private readonly ServiceUnit serviceUnit;

    private IRepository<Contact> contactRep
    {
        get { return serviceUnit.unitOfWork.Repository<Contact>(); }
    }

    private IRepository<ContactUserProfile> contactUserProfileRep
    {
        get { return serviceUnit.unitOfWork.Repository<ContactUserProfile>(); }
    }

    public ContactService(ServiceUnit serviceUnit)
    {
        this.serviceUnit = serviceUnit;
    }

    public IEnumerable<ContactUserProfile> GetContactsForUser(int marketId, int userId, int status)
    {
        return contactUserProfileRep
            .Query()
            .Where(u => u.Contact.MarketId == marketId)
            .Where(cup => cup.UserProfileId == userId)
            .Where(c => c.Deleted == false)
            .Where(c => c.Contact.Status == status)
            .ToList();
    }
}

让我们解释一下我如何使用所有这些代码。首先,我不想在我的 gui 层中依赖实体框架,并且使用这个服务包装器(ServiceUnit)我不必引用实体框架。

每个页面请求都会创建一个 ServiceUnit,而 ServiceUnit 创建一个新的 UnitOfWork 来保存整个 EntityFramework 上下文。

例如,联系页面创建一个 ServiceUnit 和一个 ServiceContact 并注入服务单元,所以我有相同的请求上下文。

这种模式会导致任何问题吗?只是想看看我是否错过了这里重要的事情。

4

1 回答 1

2

你需要“ServiceUnit”类吗?为什么不在您的服务中直接使用 UnitOfWork?

我的建议基本上是有四个项目:

  • 数据访问层项目:EF DbContext、存储库、UnitOfWork。参考“实体”项目。

  • 实体项目:EF 实体(如果您想在整个解决方案中共享 EF 实体)。不引用任何其他项目。

  • 服务层项目:ContactService等。每个都有UnitOfWork注入其中。参考“数据访问层”和“实体”项目。

  • GUI 项目:使用您的 UI。参考“实体”和“服务层”项目。

我认为 ServiceUnit 是一个不必要的抽象,服务可以直接处理 UnitOfWork(除非我遗漏了什么)。

顺便说一句,我不建议从您的存储库中公开 IQueryable(正如有人在另一个问题上向我建议的那样)。一旦你公开它,查询就会在你的存储库之外执行,因此你会失去对其执行的控制(异常处理等)。如果您搜索一下,您会发现对此存在一些争议。

于 2013-09-17T13:49:06.963 回答