Marco
Marco

Reputation: 784

Entity Framework - infrastructure in WPF/MVVM application

I'm using EF for the first time, in a WPF application, using MVVM pattern. I read a lot of stuff but I couldn't end up with a solution. My problem is how to integrate EF in my app.

The most common way I found is build your own Repository + UnitOfWork. I don't like it. Basically because I already have DbContext and DbSet that can work as unit of work and repository, so why reinvent the wheel?

So I tried to use DbContext directly from view models like this

public class BookCollectionViewModel : ViewModelBase
{
    public void LoadCollection()
    {
        Books.clear();
        var books = new List<Book>();
        using(var ctx = new DbContext())
        {
            books = ctx.DbSet<Book>().ToList();
        }
        books.Foreach(b => Books.Add(b));
    }

    ObservableCollection<Book> Books { get; } = new ObservableCollection<Book>();
}

But I don't like to use DbContext directly from view models, so I built a service layer

public class DbServices
{
    public TReturn Execute<TEntity>(Func<IDbSet<TEntity>, TReturn> func)
    {
        TReturn retVal = default(TReturn);
        using(var ctx = new DbContext())
        {
            retVal = func(ctx.DbSet<TEntity>());
        }
        return retVal;
    }
}

public class BookCollectionViewModel : ViewModelBase
{
    private DbServices mDbServices = new DbServices();

    public void LoadCollection()
    {
        Books.clear();      
        var books = mDbServices.Execute<Book>((dbSet) => return dbSet.ToList());
        books.Foreach(b => Books.Add(b))
    }

    ObservableCollection<Book> Books { get; } = new ObservableCollection<Book>();
}

But this way every action is atomic, so when I modify an entity I have to call SaveChanges() every time or loose changes, because DbContext is always disposed. So why not create a class-wide DbContext?

public class DbServices
{
    private Lazy<> mContext;

    public DbServices()
    {
        mContext = new Lazy<TContext>(() => {return new DbContext();});
    }

    public TContext Context { get { return context.Value; } }

    public TReturn Execute<TEntity>(Func<IDbSet<TEntity>, TReturn> func)
    {
        return func(Context.DbSet<TEntity>());
    }
}

Unfortunately, this way again doesn't work, because once a dbcontext is created, it is never disposed... So how about explicitly Open/Close the DbContext?

The question is: Where and how should I create/dispose the DbContext? The only thing I'm sure of is that I don't want to rebuild repository and unit of work, since they already exist as DbContext and DbSet...

Upvotes: 2

Views: 4785

Answers (1)

The Mean Fiddler
The Mean Fiddler

Reputation: 21

I'm in the same position. I find that any persistent repository on the client side causes users not to see each others' changes.

Here's a good video explaining why EF is not the same as a repository
https://www.youtube.com/watch?v=rtXpYpZdOzM

Also I found an excellent end-to-end tutorial on WPF,MVVM & EF
http://www.software-architects.com/devblog/2010/09/10/MVVM-Tutorial-from-Start-to-Finish.
In this he exposes the data through a WCF data service and detaches them from the dbcontext straight away.
Hope it helps

Upvotes: 0

Related Questions