0

How do you update an entity in EF 4?

For example:

1) Use AutoMapper to generate the CategoryEditModel from a Category entity from the Service Layer.

2) Pass the EditModel to the View. Great!!

3) Post back the EditModel, use AutoMapper to take the CategoryEditModel --> Category.

4) Take that Category and pass it off to the Service Layer which passes it off to the Repository which in turn does an ObjectSet.Attach(TEntity).

Tells me the ObjectStateManager has another object with the same key???

I am using Ninject to inject the Controller with the Service and UnitOfWork, the Service with a Repository, the Repository with a UnitOfWork. The UnitOfWork is scoped per request.

It seems something is being held in cache maybe?

Do I have to call dispose on the UOW or will Ninject take care of it? It does implement IDisposable, and in the dispose it disposes of the context.

Sam
  • 15,336
  • 25
  • 85
  • 148
  • Are you scoping your context per HTTP request? Did you create a IDatabaseFactory implementation to get the DatabaseContext for you UoW and Repositories? – Paul Mar 09 '11 at 03:49
  • @Paul - I have the .InRequest at the end of the mapping. IDatabaseFactory? I don't know what that is. – Sam Mar 09 '11 at 04:38
  • Generally you would create a IDatabaseFactory with one method, MyContext Get(); Your IRepository and IUnitOfWork would use the IDatabaseFactory Get method to get the current context. This class would also implement IDisposable. Check out a sample implementation here : http://stackoverflow.com/questions/4442828/entity-framework-4-ctp-4-ctp-5-generic-repository-pattern-and-unit-testable/4458250#4458250 – Paul Mar 09 '11 at 04:54
  • You aren't showing any code, but as far as I understand you can check if the context is being disposed by setting a breakpoint in the `UnitOfWork` `Dispose` method (which, if I understood correctly, calls the `ObjectContext` `Dispose` method). When you load/refresh a page, the breakpoint should be hit before you actually get the page loaded in the browser. – Yakimych Mar 09 '11 at 10:46

2 Answers2

0

Entity Contexts cache objects. It's generally considered wise to keep the life of a particular context quite short. I do this by using a factory within each repository method:

public SomeObject GetSomeObjectById(int id)
{
    using (var context = _contextFactory.Get())
    {
        return context.SomeObjects.SelectSingle(o => o.Id == id);
    }
}

If you're quite certain that you want to follow the one-context-per-request model, you'll need to load the entity you want out of the context (which should be free if you use context.GetObjectByKey because it sounds like it's cached in this case), change the values on the object, and then save changes.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • How do you handle using multiple services/repositories in one controller action and making them all work off the same context? – Sam Mar 09 '11 at 00:56
  • @Sam Striano: They don't all work off the same context. As you can see from the code, I'm creating and disposing a context each time a repository method is called. – StriplingWarrior Mar 09 '11 at 16:47
0

I think you should use only a single Entity Framework Session object without having repository. Take a look at this post : Question about Interfaces and DI? and let me know if you have questions. It's code-first and it works perfectly for me.

Hope it helps you!

Community
  • 1
  • 1
VinnyG
  • 6,883
  • 7
  • 58
  • 76
  • So no Repository or Service layer at all? Does your controller get injected with one of these each request? – Sam Mar 09 '11 at 02:54
  • No only a Session object witch is strongly typed, you can take a look at MVC starter site on codeplex : http://mvcstarter.codeplex.com/ it helps a lot to start the right way. My controller get injected with an ISession object, then I can do all I want with database using LINQ, exemple : _session.Where(x => x.Name == "Vinny"), do the changes and call _session.CommitChanges() when done. – VinnyG Mar 09 '11 at 03:11