EF ObjectContext的,服务和信息库 - 管理上下文生存期。 [英] EF ObjectContext, Service and Repository - Managing context lifetime.

查看:89
本文介绍了EF ObjectContext的,服务和信息库 - 管理上下文生存期。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是相当新的MVP和实体框架世界如此容忍我。

I am fairly new to the MVP and the Entity Framework world so bear with me.

我现在有一个视图+演示相结合,认为有两个事件编辑和删除并演示只是侦听这些事件。我也有一个服务对象和存储库设置。服务层采用其采取的ObjectContext因此施工顺序(在顶部对象传递给它下面的一个部分存储库实现:

I currently have a View + Presenter combination, the view has two events Edit and Delete and the presenter just listens for these events. I also have a service object and repositories set up. The service layer takes some repository implementations which take an ObjectContext so the order of construction is (passing in the top object to the one below it:

ObjectContext
   |
   V
Repositries
   |
   V
Service Object
   |
   V
Presenter

现在的问题是,当我创建顶部对象上下文,这是活着的全部时间的主持人是活着的含义,编辑和删除利用从服务相同的上下文实例。

Now the problem is that when I create object context at the top, It's alive for the whole time the presenter is alive meaning that Edit and Delete use the same context instance from the service.

于是打电话ServiceObject.Delete和ServiceObject.Edit使用相同的上下文,这使得它很难管理变革跟踪。从我了解的情况下确实应该只是短暂的,只为一个工作单元,对我编辑和删除都不同批次的工作。

So calling ServiceObject.Delete and ServiceObject.Edit use the same context which makes it hard to manage change tracking. From what I understand the context should really only be short lived and only for a unit of work, to me Edit and Delete are both different lots of work.

你怎么做DI与实体框架和仍然管理方面的生活时间?

How do you do DI with the entity framework and still manage context life time?

我看到的人只是新了中端对象上下文的信息库,这是一个。良好格局

I have seen people just new up the object context in side the repository, is this a good pattern.

或者我应该做的,在服务对象,是这样的:

Or should I do that in the service object, something like:

ServiceObject{
  public void Edit(// some args) {
     Using(var context = new MyObjectContext) {
         var repo = new MyRepo(context);
         var entity = repo.GetForID(12);
         // Do some stuff for edit
         context.SaveChanges();
     }
  }
}



但如果我这样做,我不再是通过我的一个仓库到ServiceObject的构造函数,而不是做DI :(。

But If I do it like that I am no longer passing my repository into the constructor of ServiceObject and not doing DI :(.

我可以在这种情况下怎么办?

What can I do in this situation?

有谁知道任何开源项目,我可以看看,可以帮助我解决这个问题。

Does anyone know any open source projects that I can look at that may help me with this problem.

感谢。

推荐答案

我会从顶部(主持人)去描述参与者之间的关系。

I will go from top (presenter) and describe the relations between participants.

演示者通过依赖获得服务对象服务功能是通过其合同概述:

Presenter gets service object through dependency. Service functionality is outlined using its contract:

class Presenter 
{
  public Presenter(IService service)
  {
     ... 
  }
}

Service实现从特定的数据访问层实现抽象出来的​​。基本上只要服务执行需要它创建工作单元的实例,并部署它时,它完成了数据源的交互有所行动。

Service implementation is abstracted from particular data access layer implementation. Basically whenever service performs some action that requires data source interaction it creates an instance of unit of work and disposes it when it finished.

interface IService
{
  void Do();
}

class Service : IService
{
  private readonly IUnitOfWorkFactory unitOfWorkFactory;
  public Service(IUnitOfWorkFactory unitOfWorkFactory)
  {
    this.unitOfWorkFactory = unitOfWorkFactory;
  }

  public void Do()
  {
    // Whenever we need to perform some data manipulation we create and later dispose
    // dispose unit of work abstraction. It is created through a factory to avoid 
    // dependency on particular implementation.
    using(IUnitOfWork unitOfWork = this.unitOfWorkFactory.Create())
    {
       // Unit of work holds Entity Framework ObjectContext and thus it used 
       // create repositories and propagate them this ObjectContext to work with
       IRepository repository = unitOfWork.Create<IRepository>();
       repository.DoSomethingInDataSource();

       // When we are done changes must be commited which basically means committing
       // changes of the underlying object context.
       unitOfWork.Commit();
    }
  }
}


/// <summary>
/// Represents factory of <see cref="IUnitOfWork"/> implementations.
/// </summary>
public interface IUnitOfWorkFactory
{
	/// <summary>
	/// Creates <see cref="IUnitOfWork"/> implementation instance.
	/// </summary>
	/// <returns>Created <see cref="IUnitOfWork"/> instance.</returns>
	IUnitOfWork Create();
}

/// <summary>
/// Maintains a list of objects affected by a business transaction and coordinates the writing out of 
/// changes and the resolution of concurrency problems.
/// </summary>
public interface IUnitOfWork : IDisposable
{
	/// <summary>
	/// Creates and initializes repository of the specified type.
	/// </summary>
	/// <typeparam name="TRepository">Type of repository to create.</typeparam>
	/// <returns>Created instance of the repository.</returns>
	/// <remarks>
	/// Created repositories must not be cached for future use because once this 
	/// <see cref="IUnitOfWork"/> is disposed they won't be able to work properly.
	/// </remarks>
	TRepository Create<TRepository>();

	/// <summary>
	/// Commits changes made to this <see cref="IUnitOfWork"/>.
	/// </summary>
	void Commit();
}

/// <summary>
/// Represents factory of <see cref="UnitOfWork"/>s. 
/// </summary>
public class UnitOfWorkFactory : IUnitOfWorkFactory
{
	private readonly IUnityContainer container;

	/// <summary>
	/// Initializes a new instance of the <see cref="UnitOfWorkFactory"/> class.
	/// </summary>
	/// <param name="container">
	/// Dependency injection container instance used to manage creation of repositories 
	/// and entity translators.
	/// </param>
	public UnitOfWorkFactory(IUnityContainer container)
	{
                 this.conainer = container;
	}


	/// <summary>
	/// Creates <see cref="IUnitOfWork"/> implementation instance.
	/// </summary>
	/// <returns>Created <see cref="IUnitOfWork"/> instance.</returns>
	public IUnitOfWork Create()
	{
		var unitOfWork = this.container.Resolve<UnitOfWork>();
		unitOfWork.SetupObjectContext();
		return unitOfWork;
	}

     ... other members elidged for clarity
}

IUnitOfWork的实施收到IUnityContainer的实例,然后创建子容器并有注册ObjectContext的实例。这个子容器将用于创建存储库和传播ObjectContext的

The implementation of IUnitOfWork receives instance of IUnityContainer and then creates child container and registers ObjectContext instance there. This child container will be used to create repositories and propagate ObjectContext.

下面是IUnitOfWork的简化实现:

Here is a simplified implementation of IUnitOfWork:

class UnitOfWork : IUnitOfWork
{
  private readonly IUnityContainer container;
  private ObjectContext objectContext;

  public UnitOfWork (IUnityContainer container)
  {
    this.container = container.CreateChildContainer();
  }

  public void SetupObjectContext()
  {
    this.objectContext = ... // Create object context here
    this.container.RegisterInstance(context.GetType(), context);
  }

  public void Create<TRepository>()
  {
    // As long as we registered created object context instance in child container
    // it will be available now to repositories during resolve
    return this.container.Resolve<TRepository>();
  }

  public void Commit()
  {
     this.objectContext.SaveChanges();
  }
}

class Repository : IRepository
{
  private readonly SomeObjectContext objectContext;

  public Repository(SomeObjectContext objectContext)
  {
    this.objectContext = objectContext;
  }

  public void DoSomethingInDataSource()
  {
    // You can use object context instance here to do the work
  }
}

这篇关于EF ObjectContext的,服务和信息库 - 管理上下文生存期。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆