什么是管理的DataContext最佳做法? [英] What are best practices for managing DataContext?

查看:107
本文介绍了什么是管理的DataContext最佳做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在努力使我的实体持续性无知,让我的仓库可测试的,我已经实现了一个存储库模式,像这样:

In an effort to make my entities persistent ignorant and make my repositories testable, I've implemented a repository pattern like so:

public interface IJobRepository : IRepository<Job>
{
    Job GetJobById(int jobId); //Special case where I'm eager loading other entities
    void SaveJob(Job job, Job originalJob);
}

public class JobRepository : IJobRepository
{
    private readonly IContext _context;

    public JobRepository()
    {
        _context = new CustomObjectContext();
    }

    public JobRepository(UnitOfWork unitOfWork)
    {
        _context = unitOfWork.Context;
    }

    //Basic GetAll, GetById, Add and Delete methods from IRepository<T> Interface here
    //omitted for brevity

    public Job GetJobById(int jobId)
    {
        var job = _context.Jobs.Include("Company").Include("Location").
            Include("PlantInfo").Where(j => j.Jobid == jobId).SingleOrDefault();

        _context.DisposeContext();

        return job;
    }

    public void SaveJob(Job job, Job originalJob)
    {
        if (job.Jobid > 0)
        {
            // Update
            _context.Jobs.Attach(originalJob);
            _context.PlantInfoes.Attach(originalJob.PlantInfo);
            _context.Jobs.ApplyCurrentValues(job);
            _context.PlantInfoes.ApplyCurrentValues(job.PlantInfo);

        Note: ApplyCurrentValues is an extension method I'm using on the ObjectSet

        }
        else
        {
            // Create
            _context.Jobs.AddObject(job);
        }

        _context.Save();
    }
}

public class UnitOfWork
{
    private readonly IContext _context;

    public UnitOfWork()
    {
        _context = new CustomObjectContext();
    }

    public UnitOfWork(IContext context)
    {
        _context = context;
    }

    public string Save()
    {
        return _context.Save();
    }

    internal IContext Context
    {
        get { return _context; }
    }
}

public interface IContext
{
    IObjectSet<Job> Jobs { get; }
    IObjectSet<Company> Companies { get; }
    IObjectSet<Location> Locations { get; }
    IObjectSet<PlantInfo> PlantInfoes { get; }
    string Save();
}

我从ObjectContext的继承IContext ...所以我的理解是,我将只使用重载的构造函数库,方便单元测试或使用它的情况下,我想使用基于相同的上下文(不可取这个帖子我发现SO <一个href=\"http://stackoverflow.com/questions/3653009/entity-framework-and-connection-pooling/3653392#3653392\">\"Entity框架和连接池 - 这是正确的。

此外,假设的背景下只得到处置的垃圾收集库的时候,我必须明确处置的背景下,以避免实体对象不能被IEntityChangeTracker的多个实例引用。除了之前连接的实体时,保存。

Also, assuming the context only gets disposed when the repository is garbage collected, I have to dispose the context explicitly to avoid the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker." exception when attaching the entity prior to a save.

这是说,究竟是什么在让你的实体持续性无知和存储库可测试的方式管理的DataContext最佳做法?

That said, what is the best practice for managing the DataContext in a manner that keeps your entities persistent ignorant and repositories testable?

注:这是一个asp.net web应用;的UnitOfWork并IContext实现基于实例由朱莉娅·勒曼CH24编程实体框架,第二版。

Note: This is an asp.net webapplication; UnitOfWork and IContext implementation was based on examples from "Programming Entity Framework", Second Edition by Julia Lerman Ch24.

在此先感谢!

推荐答案

首先,我会确保无论我的消耗品对象(无论是资料库或单位的工作,根据您的设​​置)实施 IDisposable的。当你的consumbed对象被处置,那么你将处置您的基本背景。

Firstly, I would ensure that whatever my "consumable" object is (either repository or unit of work, depending on your setup) implements IDisposable. When your consumbed object is disposed of, then you would dispose your underlying context.

例如,如果您使用的的UnitOfWork 作为消耗品对象(被创建,并呼吁在应用程序中的一个),它看起来是这样的:

For instance, if you're using your UnitOfWork as the consumable object (the one that gets created and called in your application), it would look something like:

public class UnitOfWork : IDisposable
{
    // All the other stuff you had before plus:
    public void Dispose ()
    {
        if (_context != null)
        {
            _context.Dispose ();
        }
    }
}

(注意:这也可以在你的仓库做,如果他们是那些被直接饮用)

(Note: This can also be done on your repositories if they're the ones being consumed directly)

然后,你在你的应用程序中的几个选项。如果你要使用的UnitOfWork 直接,你可以用它喜欢的:

And then, you have a few options in your application. If you are going to use the UnitOfWork directly, you can use it like:

public void SomeMethodThatAccessesYourData ()
{
    using (var unitOfWork = new UnitOfWork (/*Load in the context*/))
    {
        // Access your data here.
    }
}

或者,当Web窗体或MVC对象置于您的Web窗体或MVC对象就可以使用构造注入和它的配置:

Or, in your Web Forms or MVC object you can use constructor injection and dispose of it when the Web Forms or MVC object is disposed of:

//  If you're using MVC:
public class MyController : Controller
{
    private UnitOfWork _unitOfWork;

    public MyController (UnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public override Dispose (bool Disposing)
    {
        if (Disposing && _unitOfWork != null)
        {
            _unitOfWork.Dispose ();
        }
    }
}

同样的想法代表了一个Web表单

使用构造函数重载的主要原因是反转(IOC)。它有助于这两个单元测试和生产code与 IoC容器使用时。的WebForms并不太适合国际奥委会,但它与MVC真的很容易。

The main reason for using the constructor overload is for Inversion of Control (IOC). It helps with both unit testing and with production code when used with an IoC Container. WebForms doesn't lend itself well to IoC, but it is really easy with MVC.

修改

我真的没有看到你的资料库和工作单元的连接。通常你从工作单位访问存储库,或在其他实现,你从你的目标存储库要求的工作单元。在您的实现(我的理解是不是你自己的),似乎没有必要为。

I don't really see the connection with your repositories and the unit of work. Usually you access the repositories from a unit of work or, in other implementations, you request a unit of work from your target repository. In your implementation (which I understand is not your own) there seems to be no need for both.

编辑2

如果该UOW是矫枉过正您的应用程序,你知道你可以使用IoC容器注入你的IContext,而你没有很多的资源库,你可以这样做:

If the UoW is overkill for your application, and you know you can use IoC to inject your IContext, and you don't have very many repositories, you can do something like:

public IRepository<T> : IDisposable { }
public IJobRepository : IRepository<Job> { /* All the stuff you put here */ }
public JobRepository : IJobRepository
{
    private IContext _context;

    ...

    public void Dispose ()
    {
        if (_context != null)
        {
            _context.Dispose ();
        }
    }

    public JobRepository (IContext context)
    {
         _context = context;
    }
}

那么,你如何使用它取决于你的特定的任务。我不是这个直接用IRepository的粉丝,但这个答案越来越太长。

Then, how you use it depends on your specific task. I'm not a fan of this direct use of IRepository, but this answer is getting too long.

这篇关于什么是管理的DataContext最佳做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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