1

Good day,

I'm using repository pattern. But someone advised me to use include Unit of Work. I read a lot of articles and honestly I found a docs that are too complicated to understand.

Supposing I have a non-generic repository.

// My Interface 
public interface IProductRepository{
    IQueryable Products();
    IQueryable ProductById(int id);
    void InsertProduct(Product product);
    void UpdateProduct(Product product);
    void DeleteProductById(int id);
}

// Abstract Implementation

public class ProductRepository : IProductRepository{
    private readonly MyDbContext context;

    public ProductRepository(MyDbContext context){
        this.context= context;
    }

    public IQueryable Products(){  
        context.Product(); 
    }
    public IQueryable ProductById(int id){ 
        context.Product().Where(prod=>prod.Id == id);    
    }
    public void InsertProduct(Product product){
        context.Product.Add(product);
        context.SaveChanges();
    }
    public void UpdateProduct(Product product){
        context.Product.Update(product);
        context.SaveChanges();
    }
    public void DeleteProductById(int id){
        var product = ProductById(id);
        context.Product.Remove(product);
        context.SaveChanges();
    }
}

My question is, how can I use Unit of Work here? Can you please show me a code below. It will be so much helpful for me to understand.

jsonGPPD
  • 987
  • 4
  • 16
  • 31
  • 2
    Your underlying ORM (Entity Framework) _already_ follows both repository and unit of work patterns. So just throwing away your abstration over another (identical) abstration will reach the goal. But if you insist - just duplicate its functionality. Remove all `context.SaveChanges` from `UpdateProduct`, `DeleteProduct` etc, and add separate `SaveChanges` method (which will of course do nothing more than `cotnext.SaveChanges`). – Evk Mar 13 '18 at 05:30
  • You mean, I don't need to learn unit of work when using EF? Is that what you mean? Because EF has it's own Repository and unit of work patterns? – jsonGPPD Mar 13 '18 at 05:50
  • If you don't know what unit of work is - then sure you need to learn what is it, how are you going to implement it otherwise. And then you will see that EF DbContext already follows unit of work pattern. – Evk Mar 13 '18 at 06:02
  • Good Cross ref: https://stackoverflow.com/questions/10776121/what-is-the-unit-of-work-pattern-in-ef – Gavin Stevens Mar 13 '18 at 06:08
  • @Evk if EF has it, so I don't need to implement Unit of Work pattern right? – jsonGPPD Mar 13 '18 at 06:13
  • @jsonGPPD your repository abstraction removed unit of work capabilities, so if you want to leave your repository - you need to also implement unit of work pattern (as described in my first comment). But because EF already follows both repository and unit of work - you can just remove your repository and use EF context directly, because your repository doesn't add anything useful to it (in its current state). – Evk Mar 13 '18 at 06:15
  • Oh so you mean, If I implement my own repository pattern under EF, I need to implement unit of work. Otherwise, I'll just use EF by default? Am I getting it right? Since I've read that DbContext in EF is already a UnitOfWork class – jsonGPPD Mar 13 '18 at 06:28
  • Unit of work is something you define for your domain. Most of the time it is not restricted to one repository. For example if you want to do a inventory update when updating the product, your unit of work will span across both productRespository and productInventroryRepository. Using EF will not automatically provide you with the unit of work you need. – Low Flying Pelican Mar 13 '18 at 06:41
  • But @Evk I'll listen to your advise to create a method for Save but am I doing it wrong? I'm just following with this video https://www.youtube.com/watch?v=9_HYpX83A04&t=24s & https://www.youtube.com/watch?v=oKyzza01rzA – jsonGPPD Mar 13 '18 at 11:08
  • https://learn.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design – Adam Feb 10 '19 at 14:07

3 Answers3

2

In your IProductRepository add a Save method

// My Interface 
public interface IProductRepository{
    // ...
    void Save();
}

Then in concrete ProductRepository, you do two things:

  1. Remove all calls to context.SaveChanges();
  2. In IProductRepository.Save implementation, call context.SaveChanges()

Do all operations on the dbcontext, and in the end call Save().

static void main() {
    // ...
    this.productRepository.InsertProduct(product1);
    this.productRepository.InsertProduct(product2);
    this.productRepository.InsertProduct(product3);
    this.productRepository.Save();
}

That's the gist of unit of work.

jokab
  • 671
  • 7
  • 14
1

The main reason why you need unit of work in your project is you need to make sure all your repository have same context. The relationship between unit of work and repository like the relationship between DbContext and DbSet in Entity framework.

If you want to implement your UnitOfWork you can ref this link: https://codereview.stackexchange.com/questions/47879/unit-of-work-and-repository-with-entity-framework-6

Tan Sang
  • 1,897
  • 1
  • 16
  • 28
0

This is really more of an answer to your questions in the comments about EF doing the work
If you look at how EFCore does this, you actually define a context and define what classes you want inside that context. From https://learn.microsoft.com/en-us/ef/core/ they define a BloggingContext that inherits from DbContext. The example below is from microsoft:

    public class BloggingContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=localdb)\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;");
    }
}

They have a Blog class and a Post class in this example that get created into tables when a migration and update are ran on the database(https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/). Now that you have Blog and Post defined inside the BloggingContext you can create an instance(good to use dependency injection you can read more about that here if you like https://learn.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext) of the BloggingContext and use linq to your hearts content, no need for a custom repository or unit of work. EF does the work once you have defined what classes you want in what context. With that said, we do use repository and unit of work where I work, if there is a reason to use the patterns great, but past that or learning it for yourself, EF does really well.

Adam
  • 395
  • 4
  • 9