0

Currently working on an MVC application using the MVVM pattern. It was originally written so that all the ViewModels inherited from the same BaseViewModel, which spun up a single Entity Framework repository, like so:

public abstract class BaseViewModel : INotifyPropertyChanged
{
    private static MyRepository _rep;
    protected static MyRepository rep
    {
        get
        {
            if (_rep == null)
                _rep = new MyRepository();
            return _rep;
        }
    }
}

The application as I inherited it had virtually no unit testing, so I decided to do some refactoring to make it more testable. So I put an interface over the repository, and gave each viewmodel its own copy, so it could be mocked out for testing:

public class MyViewModel : BaseViewModel
{
    private IMyRepository _rep;

    public AvailabilityHistoryViewModel()
        : this(new MyRepository())
    { }

    public MyViewModel(IMyRepository rep)
    {
        _rep = rep;
        DoStuff();
    }
}

Which is fine for the majority of cases. But then I came across a previously functional button that suddenly caused the application to crash with the dreaded "entity object cannot be referenced by multiple instances of IEntityChangeTracker" error.

It turns out that there's a UserControl that's used in several places in the application which also inherits from BaseViewModel and so has its own copy of the repository.

public abstract class BaseTreeViewItem : BaseViewModel
{ }

When this is used inside a parent viewmodel, and its properties are passed around, it's quite possible to end up with an EF object that's been created with the UserControl repository being passed to the ViewModel and saved with its repository - which, because they're different contexts, causes the crash.

The easy fix is simply to back out my changes, and have the ViewModels that use this UserControl go back to using the BaseViewModel repository. But that's ugly. A proper fix for this, rearranging things so that the UserControl doesn't have its own context, is going to take longer that I've realistically got. Is there another way?

1 Answer 1

1

I might miss something, but it seems to me that having singleton repositories would solve your problem. You already use them through interface, so you could simply inject them.

Sign up to request clarification or add additional context in comments.

5 Comments

It would - in fact the original model had a singleton repository. However, to do this and maintain my testability would require me to implement dependency injection, which is a whole kettle of fish in itself, even using an off-the-shelf package like Ninject. Or am I missing something obvious?
Yes you should then implement dependency injection, which is a really good pattern to have in your architecture. At first it might seem to be extra work, but the flexibility it provides through loose coupling improves the maintainability and testability of your code extremely.
And implementing a good framework code based framework like Ninject is not that complicated as it seems. The earlier you do it in your project the less work it means. They have really nice tutorials in their Dojo
Yeah but that's part of the problem - it's not early, this is a released app and I'm firefighting bad architectural decisions made before I arrived on the project.
Ah okay, it makes things a bit more complex. Though I would still advice you to use DI. The effort you put into it now, will definitely pay off later. If you have a reliable test base then you should not be afraid of "some refactoring". Otherwise you should start building it :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.