I've been following Darin's answer to a question I had on slimming down my controllers and I'm running into problems with this IEntityChangeTracker exception:

An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

Here's my model binder:

public class PostModelBinder : IModelBinder
{
    private readonly IPostRepository _repository;

    public PostModelBinder(IPostRepository repository)
    {
        _repository = repository;
    }

    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext)
    {
        var postIDValue = controllerContext.Controller.ValueProvider.GetValue("postID");
        int postID;

        if (postIDValue == null || !int.TryParse(postIDValue.AttemptedValue, out postID))
            return null;

        return _repository.FindPost(postID, filterByPublished: true);
    }
}

After this, my custom action filter simply carries out a bit of validation on the post and redirects if the post isn't valid. Up until this point, everything is fine. The error happens in my controller when I try to update the post read count:

public class PostsController : Controller
{
    private IPostRepository postRepository;

    // snip...

    [AutoMap(typeof(Post), typeof(PostViewModel)), HttpGet]
    [PostActionFilter]
    public ActionResult ShowPost(Post model)
    {
        postRepository.PostVisited(model);

        return View(model);
    }
}

I understand IEntityChangeTracker's complaining because I effectively end up with 2 repositories referencing the same object and that just seems like bad mojo waiting to happen. I know I could push the PostVisited() call into PostModelBinder but updating a model doesn't seem like behaviour that belongs there.

Is there another way around this?

Thank you.

1

There are 1 answers

4
Steve Wilkes On BEST ANSWER

From the error, I assume your two IPostRepository implementation objects use different Entity Framework object contexts; you can fix this by using the same object context throughout a request.

Some DI containers support per-request object lifetimes, otherwise you can lazy-load and store your object context in HttpContext.Items and dispose of it at the end of the request, as mentioned in this question.