Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF/EntityFramework上下文生存期 问题_C#_Wpf_Entity Framework_Architecture - Fatal编程技术网

C# WPF/EntityFramework上下文生存期 问题

C# WPF/EntityFramework上下文生存期 问题,c#,wpf,entity-framework,architecture,C#,Wpf,Entity Framework,Architecture,我们目前在WPF应用程序上遇到了架构问题。它涉及EntityFramework上下文管理,只实例化一次,并在应用程序的整个生命周期中使用。因此,我们最终会遇到缓存问题,实体在加载一次时不会更新。我们的实体在使用应用程序时已过时 技术规格 Wpf项目 .Net Framework 4客户端配置文件 MEF包含在框架4.0 System.ComponentModel.Composition中 设计模式MVVM 多用户应用程序 建筑学 这是当前体系结构的模式 服务层 管理对业务规则业务层的调用 完成业

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

技术规格 Wpf项目 .Net Framework 4客户端配置文件 MEF包含在框架4.0 System.ComponentModel.Composition中 设计模式MVVM 多用户应用程序 建筑学 这是当前体系结构的模式

服务层 管理对业务规则业务层的调用 完成业务规则后通过UnitOfWork保存上下文 只能由ViewModel调用 业务层 定义业务规则 只能由服务层调用 存储库层 执行更改上下文数据的方法插入、更新、删除 继承只读存储库 只能由业务层调用 只读存储层 执行返回数据选择的方法 可以称为随处可见的视图模型、服务层、业务层 工作单元 管理上下文实例 保存上下文 上下文仅适用于存储库 密码 视图模型 服务层 业务层 只读存储层 在第一次使用MEF组合服务期间,将使用实例化上下文的默认构造函数实例化UnitOfWork

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

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

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


请随意提问!如果需要,我可以附加一个测试项目来突出问题。

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

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

  unitOfWork.Save();
}
我修改了UnitOfWork,使其实现IDisposable。这将允许您处理EF上下文,如果未调用Save,还可能回滚事务。如果不需要额外的事务处理,甚至可以去掉UnitOfWork类,因为它只包装EF上下文,而可以直接将EF上下文用作工作单元


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

概述清楚区分的用例,这些用例将保持自己的生命周期范围。这也有助于防止在使用WPF时非常频繁的其他资源泄漏

考虑通用算法:

初始化生存期范围。 使用范围: 分配视图和其他WPF资源,分配业务层,数据访问UoW,上下文,repo。 从数据库加载数据并将其显示给用户。 等待用户操作1。 进行一些更改或从数据库加载更多数据。 更新用户的数据表示形式。 转到1,直到场景完成。 处置范围,取消分配资源。 问题是您的范围当前是您的应用程序

现在假设您在视图级别管理范围。分配、显示视图、获取用户输入、保存更改,然后立即处理整个对象树


显然,您应该灵活使用范围。有时在视图级别使用它会很有用,比如编辑项,有时它会在多个视图中传播,比如向导。您甚至可以在VisualStudio中打开项目时维护数据驱动的作用域;开始生命周期范围以管理所有资源,这些资源应在项目“生命周期”期间可用。

如果不维护上下文,您如何实现工作单元的目标?一件事是,当您在MEF中创建任何依赖IDisposable的Dispose方法的OnObject时,它在容器被释放之前不会被释放。很抱歉,回复太晚。我想你让我走上了正确的道路。我从你的代码开始,我设法解决我的问题。每个服务方法都通过unitofworkfactory实例化unitofwork。像这样,我的上下文范围是服务方法
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;
   }
}
public class OrderReadOnlyRepository : ReadOnlyRepositoryBase<DataModelContainer, Order>, IOrderReadOnlyRepository
{
   [ImportingConstructor]
   public OrderReadOnlyRepository (IUnitOfWork uow) : base(uow)
   {
   }
}
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);
   }
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();
   }
}   
using (var unitOfWork = unitOfWorkFactory.Create()) {
  // Do work ...

  unitOfWork.Save();
}