【发布时间】:2014-11-28 15:59:19
【问题描述】:
问题
我们目前在 WPF 应用程序上遇到架构问题。它涉及 EntityFramework 上下文管理,它被实例化一次并在应用程序的整个生命周期中使用。所以我们最终会遇到缓存问题,实体在加载一次时不会更新。我们的实体在使用应用程序时已过时。
技术规格
- Wpf 项目
- .Net Framework 4 客户端配置文件
- MEF(包含在 Framework 4.0 System.ComponentModel.Composition 中)
- 设计模式 MVVM
- 多用户应用程序
架构
这是当前架构的架构。
服务层
- 管理对业务规则的调用(业务层)
- 在业务规则完成后保存上下文(通过 UnitOfWork)
- 只能由 ViewModel 调用
业务层
- 定义业务规则
- 只能被服务层调用
存储层
- 执行更改上下文数据的方法(插入、更新、删除)
- 继承 ReadOnlyRepository
- 只能被业务层调用
ReadOnlyRepository 层
- 执行返回数据的方法(选择)
- 可以在任何地方调用(ViewModel、Service 层、Business 层)
工作单位
- 管理上下文实例化
- 保存上下文
- 上下文仅适用于存储库
代码
视图模型
[Export(typeof(OrderViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class OrderViewModel : ViewModelBase
{
private readonly IOrderManagementService _orderManagementService;
private readonly IOrderReadOnlyRepository _orderReadOnlyRepository;
[ImportingConstructor]
public OrderViewModel(IOrderManagementService orderManagementService, IOrderReadOnlyRepository orderReadOnlyRepository)
{
_orderManagementService = orderManagementService;
_orderReadOnlyRepository = orderReadOnlyRepository;
}
}
服务层
public class OrderManagementService : IOrderManagementService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IOrderManagementBusiness _orderManagementBusiness;
[ImportingConstructor]
public OrderManagementService (IUnitOfWork unitOfWork, IOrderManagementBusiness orderManagementBusiness)
{
_unitOfWork= unitOfWork;
_orderManagementBusiness = orderManagementBusiness;
}
}
业务层
public class OrderManagementBusiness : IOrderManagementBusiness
{
private readonly IOrderReadOnlyRepository _orderReadOnlyRepository;
[ImportingConstructor]
public OrderManagementBusiness (IOrderReadOnlyRepository orderReadOnlyRepository)
{
_orderReadOnlyRepository = orderReadOnlyRepository;
}
}
ReadOnlyRepository 层
public class OrderReadOnlyRepository : ReadOnlyRepositoryBase<DataModelContainer, Order>, IOrderReadOnlyRepository
{
[ImportingConstructor]
public OrderReadOnlyRepository (IUnitOfWork uow) : base(uow)
{
}
}
ReadOnlyRepositoryBase
public abstract class ReadOnlyRepositoryBase<TContext, TEntity> : IReadOnlyRepository<TEntity>
where TEntity : class, IEntity
where TContext : DbContext
{
protected readonly TContext _context;
protected ReadOnlyRepositoryBase(IUnitOfWork uow)
{
_context = uow.Context;
}
protected DbSet<TEntity> DbSet
{
get { return _context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> GetAll(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = DbSet.AsNoTracking();
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
return query.ToList();
}
public virtual IQueryable<TEntity> All()
{
return DbSet.AsNoTracking();
}
public virtual IQueryable<TEntity> AllWhere(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate).AsNoTracking();
}
public virtual TEntity Get(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate).AsNoTracking().FirstOrDefault();
}
public virtual TEntity GetById(int id)
{
TEntity find = DbSet.Find(id);
_context.Entry(find).State = System.Data.EntityState.Detached;
return DbSet.Find(id);
}
我们可以看到在构造函数中给存储库提供了上下文。 Select 方法使用“AsNoTracking()”方法不缓存实体。这是一个临时解决方案,从长远来看显然不可行。
工作单位
public class UnitOfWork : IUnitOfWork
{
private DataModelContainer _context;
public UnitOfWork()
: this(new DataModelContainer())
{
}
public UnitOfWork(DataModelContainer context)
{
_context = context;
}
public DataModelContainer Context
{
get { return _context; }
}
public int Save()
{
return _context.SaveChanges();
}
}
在第一次使用 MEF 组合服务期间,UnitOfWork 将使用实例化上下文的默认构造函数进行实例化。
备注
为了便于阅读,省略了一些代码。
要实现的目标
上下文的生命周期显然是一个问题。知道同一服务方法中的所有调用必须共享相同的上下文。
我们如何考虑修改架构以避免单一上下文?
欢迎提问!如果需要,我可以附上一个突出问题的测试项目。
【问题讨论】:
-
在不维护上下文的情况下如何实现工作单元的目的?一件事是,当您在 MEF 中创建依赖于 IDisposable 的 Dispose 方法的任何 onbject 时,它永远不会被释放,直到其容器被释放 (mef.codeplex.com/wikipage?title=Parts%20Lifetime)。
标签: c# wpf entity-framework architecture