0

I have seen good sources about Repository Pattern like the video Repository Pattern with C# and Entity Framework, Done Right and Aspnet Boilerplate. I know that the repository should not have logic to commit data, which is responsibility of the Unit of Work. But seems to me a little of overweight doing delete of parent record with children, because you may need to read the parent, all of its children, to then delete. You can see example of implementation like that, using Entity Framework in the same video, deleting authors and course. The Aspnet Boilerplate has a implementation to delete with a primary key, which read the entity before deleting too. So, I ask: can I use a delete commands and still respect the pattern? Is there any good example out there?

mqueirozcorreia
  • 905
  • 14
  • 33
  • Use [stub entities](http://stackoverflow.com/a/28261869/861716). – Gert Arnold Mar 07 '17 at 08:24
  • I think the first question to ask yourself is why you are trying to implement a repository pattern on top of DbContext, when that is already a repository and unit of work? The only somewhat good reason I hear is: "but what if we need to switch persistence layer" and this pretty much never happen in my experience. Good read here about repository being maybe not the best fit for EF: https://www.thereformedprogrammer.net/is-the-repository-pattern-useful-with-entity-framework-core/ – Thomas Schmidt Oct 08 '20 at 18:22

2 Answers2

1

I can't see how this might be an issue if you inject one Context per request or rather one Unit of work in this case, since it's the same context all across the current request, you can simply delete the parent and set cascade for its children, something like:

var product = new Product { Id = productId };
db.Entry(product).State = System.Data.Entity.EntityState.Deleted;
db.SaveChanges();

This way you do one less read, on top of that take a look at components like MediatR, and why you don't even need a repository if you use an ORM.

Hamid Mosalla
  • 3,279
  • 2
  • 28
  • 51
  • Some people argues that using DbContext could suffice the needs of the repository. I was studying this video, from Mosh, that shows when DbContext doesn't is a good Solution: https://youtu.be/rtXpYpZdOzM?t=5m3s Anyway, my question still have the same problem: To implement Repository, I always need to read a entity before delete? How could I use the Delete Command, so I'll go to the database only one time? Your solution is good to avoid the read of the children, but still reads the parent. – mqueirozcorreia Mar 07 '17 at 14:35
  • 1
    My solution doesn't read the parent, it news up an instance of the parent with the id of an already existing one, and delete it on SaveChanges, in terms of efficiency, there is no other way, again best practice is to not use a design pattern when you don't need it, but the purpose of unit of work is to have an atomic transaction, which you already have with db context which by the way is an implementation of the unit of work pattern. – Hamid Mosalla Mar 07 '17 at 15:33
  • Thank you! Nice solution and some people have given this as example here too http://stackoverflow.com/a/37802938/3424212 – mqueirozcorreia Mar 07 '17 at 21:53
  • Also take a look at [entity framework extension](https://github.com/loresoft/EntityFramework.Extended) especially future query if the performance is a priority for you, but I generally don't worry about that too much, given that programmer know how EF works. – Hamid Mosalla Mar 08 '17 at 04:47
0

I actually think:

var product = new Product { Id = productId }; // what if here you have null?? (I didn't see any checking) in the next row will be exception
if(product == null) 
    throw new ItemNotFound($"thi is custom error handler or do magic")

db.Entry(product).State = System.Data.Entity.EntityState.Deleted;
db.SaveChanges(); // better in repository layer to have async method like await 
db.SaveChangesAsync();

P.S. my vertion:

public async Task DeleteTemplate(int id) { var entity = await RepositoryContext.Set().FindAsync(id); if(entity == null) throw new ItemNotFoundException($"we don't have it in db.have nothing to remove"); RepositoryContext.Product.Remove(entity);

        await RepositoryContext.SaveChangesAsync();
    }

in real project better to use repositoryContect.