What is the unit of work pattern in EF?

后端 未结 3 1943
鱼传尺愫
鱼传尺愫 2020-12-24 01:18

I am learning EF and have seen many examples, and during my learning I came to know about using repository and unit of work patterns. I got why to use repository but I do no

相关标签:
3条回答
  • 2020-12-24 02:01

    Unit of Work

    Maintains a list of objects affected by a business transaction and coordinates the writing
    out of changes and the resolution of concurrency problems.

    enter image description here

    When you're pulling data in and out of a database, it's important to keep track of what you've changed; otherwise, that data won't be written back into the database. Similarly you have to insert new objects you create and remove any objects you delete.

    You can change the database with each change to your object model, but this can lead to lots of very small database calls, which ends up being very slow. Furthermore it requires you to have a transaction open for the whole interaction, which is impractical if you have a business transaction that spans multiple requests. The situation is even worse if you need to keep track of the objects you've read so you can avoid inconsistent reads.

    A Unit of Work keeps track of everything you do during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database as a result of your work.

    http://martinfowler.com/eaaCatalog/unitOfWork.html

    0 讨论(0)
  • 2020-12-24 02:02

    The DataContext or ObjectContext is the Unit of Work.

    So, your DAL will save, delete and retrieve objects and your DataContext/ObjectContext will keep track of your objects, manage transactions and apply changes.

    This is an example just to illustrate the idea of the solution.

    using(var context = new ObjectContext()) { // Unit of Work
        var repo = new ProductRepository(context);
        var product = repo.GetXXXXXXX(...);
        ...
    
        // Do whatever tracking you want to do with the object context. For instance:
        // if( error == false) { 
        //     context.DetectChanges();
        //     context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
        // }
    }
    

    And your repository will look like:

    public abstract class Repository {
    
        public Respository(ObjectContext context){
            CurrentContext = context;
        }
    
        protected ObjectContext CurrentContext { get; private set; } 
    }
    
    public class ProductRespository : Repository {
        public ProductRespository(ObjectContext context) : base(context){
        }
    
        public Product GetXXXXXX(...){
            return CurrentContext... ; //Do something with the context
        }
    }    
    

    Another way is to put the unit of work (Object context) globally:

    You need to define what will be your unit of work scope. For this example, it will be a web request. In a real world implementation, I'd use dependency injection for that.

    public static class ContextProvider {
    
        public static ObjectContext CurrentContext {
            get { return HttpContext.Items["CurrentObjectContext"];
        }
    
        public static void OpenNew(){
            var context = new ObjectContext();
            HttpContext.Items["CurrentObjectContext"] = context; 
        }
    
        public static void CloseCurrent(){
            var context = CurrentContext;
            HttpContext.Items["CurrentObjectContext"] = null;
            // Do whatever tracking you want to do with the object context. For instance:
            // if( error == false) { 
            //     context.DetectChanges();
            //     context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
            // }
            context.Dispose();
        }
    }
    

    In this example, ObjectContext is the unit of work and it will live in the current request. In your global asax you could add:

    protected void Application_BeginRequest(object sender, EventArgs e){
        ContextProvider.OpenNew();
    }
    
    protected void Application_EndRequest(object sender, EventArgs e){
        ContextProvider.CloseCurrent();
    }
    

    In your Repositories, you just call ContextProvider.CurrentContext

    0 讨论(0)
  • 2020-12-24 02:19

    One of the most common design patterns in enterprise software development is the Unit of Work. According to Martin Fowler, the Unit of Work pattern "maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems."

    The Unit of Work pattern isn't necessarily something that you will explicitly build yourself, but the pattern shows up in almost every persistence tool that I'm aware of. The ITransaction interface in NHibernate, the DataContext class in LINQ to SQL, and the ObjectContext class in the Entity Framework are all examples of a Unit of Work. For that matter, the venerable DataSet can be used as a Unit of Work.

    For more detail info Please click here to read this article, it's a good one.

    For Tutorial on Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC (MVC 4 and EF 5) Application (9 of 10) please click here

    For EF 6 and MVC 5 tutorial please click here

    I hope this will help, it helped me!

    enter image description here

    0 讨论(0)
提交回复
热议问题