gpt4 book ai didi

c# - WPF/EntityFramework 上下文生命周期

转载 作者:太空狗 更新时间:2023-10-29 23:30:54 26 4
gpt4 key购买 nike

问题

我们目前在 WPF 应用程序上遇到架构问题。它涉及 EntityFramework 上下文管理,它被实例化一次并在应用程序的整个生命周期中使用。所以我们最终遇到了缓存问题,实体在加载一次时不会更新。使用该应用程序时,我们的实体已过时。

技术规范

  • Wpf 项目
  • .Net Framework 4 客户端配置文件
  • MEF(包含在 Framework 4.0 System.ComponentModel.Composition 中)
  • 设计模式 MVVM
  • 多用户应用

架构

这是当前架构的架构。

architecture schema

服务层

  • 管理对业务规则的调用(业务层)
  • 在业务规则完成后保存上下文(通过 UnitOfWork)
  • 只能由 ViewModel 调用

业务层

  • 定义业务规则
  • 只能被服务层调用

存储库层

  • 执行更改上下文数据的方法(插入、更新、删除)
  • 继承ReadOnlyRepository
  • 只能被业务层调用

ReadOnlyRepository层

  • 执行返回数据的方法(select)
  • 可以在任何地方调用(ViewModel、Service层、Business层)

工作单元

  • 管理上下文实例化
  • 保存上下文
  • 上下文仅适用于存储库

代码

View 模型

[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);
}

我们可以看到context是在构造函数中给repository的。 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 将使用实例化上下文的默认构造函数实例化。

备注

为了便于阅读,省略了一些代码。

要实现的目标

上下文的生命周期显然是一个问题。知道同一服务方法中的所有调用必须共享相同的上下文。

我们如何考虑修改架构以避免出现单一上下文?

欢迎提问!如果需要,我可以附上突出问题的测试项目。

最佳答案

在您的应用程序中只有一个工作单元,但这并不是一个单元一个工作的目的。相反,您需要在每次“使用数据库”时创建一个工作单元。在您的情况下,UnitOfWork 不应是 MEF 容器的一部分,但您可以创建一个 UnitOfWorkFactory 并将其从容器中注入(inject)。然后服务可以在每次“必须完成”数据库时创建一个 UnitOfWork:

using (var unitOfWork = unitOfWorkFactory.Create()) {
// Do work ...

unitOfWork.Save();
}

我已经修改了 UnitOfWork,所以它实现了 IDisposable。这将允许您处理 EF 上下文,如果未调用 Save,还可能回滚事务。如果您不需要额外的事务处理,您甚至可以摆脱 UnitOfWork 类,因为它只是包装了 EF 上下文,您可以直接将 EF 上下文用作工作单元。

此更改将迫使您修改服务和存储库的结构方式,但您确实必须这样做,因为您的问题是在整个应用程序期间存在一个单一的工作单元。

关于c# - WPF/EntityFramework 上下文生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26181559/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com