【问题标题】:EntityFramework with UnitOfWork to Service patternEntityFramework 与 UnitOfWork 到服务模式
【发布时间】:2013-09-17 21:49:06
【问题描述】:

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

  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 并注入服务单元,所以我有相同的请求上下文。

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

【问题讨论】:

  • 在你的 UnitOfWork 实施中很高兴有 dispose 方法来处理上下文
  • 这更适合codereview。 StackOverflow 用于特定 编程问题。 (出现问题或无法上班)。

标签: c# entity-framework


【解决方案1】:

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

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

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

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

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

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

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

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

【讨论】:

  • 您好,感谢您的回复。我所有的页面都来自一个使用 ServiceUnit 进行简单创建、更新、读取功能的基本页面。这个页面是通用的,这就是为什么我需要这个额外的包装器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-29
  • 2017-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多