我的申请表中有以下图层。
我有大多数类的接口并使用DI,但是这个版本被压缩为仅显示类。
这是UnitOfWork,它将DbContext保存在我的Repository.Ef层中。
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并注入服务单元,因此我对请求具有相同的上下文。
这种模式会导致任何问题吗?如果我在这里遗漏了一些重要的东西,我只想这样做。
答案 0 :(得分:2)
您需要“ServiceUnit”课吗?为什么不直接在服务中使用UnitOfWork?
我建议基本上有四个项目:
数据访问层项目:EF DbContext,存储库,UnitOfWork。参考“实体”项目。
实体项目:EF实体(如果您想共享EF实体) 整个解决方案)。不参考任何其他项目。
服务层项目:ContactService等。每个都有UnitOfWork 注入他们。引用“数据访问层”和“实体”项目。
GUI项目:使用您的UI。引用“实体”和“服务层”项目。
我认为ServiceUnit是一个不必要的抽象,服务可以直接处理UnitOfWork(除非我遗漏了什么)。
顺便说一句,我不建议从您的存储库中公开IQueryable(正如有人在另一个问题上向我建议的那样)。暴露它之后,查询将在您的存储库外部执行,因此您无法控制其执行(异常处理等)。如果你搜索一下,你会发现有一些争议。