我的应用程序中有以下层。
- Repository.Ef(这个处理 ef 的上下文)
- 实体(这里是 ef 的所有实体)
- 核心(这一层处理所有业务,就像 Ef <> Gui 之间的包装器一样工作)
- 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 并注入服务单元,所以我有相同的请求上下文。
这种模式会导致任何问题吗?只是想看看我是否错过了这里重要的事情。