11

I'm using a single instance of DbContext scenario to shadow entire copy of the database locally in a WPF app. I've heard this is bad practice, but my database is small and I need an entire copy of it locally while the app is running.

An extension method for IQueryable, Load() lets me preload the elements of a DbSet<>, so that I can bind things to the Local property of DbSet<>. Data in the database changes rapidly, so I want to SaveChanges() and reload everything, even objects that are already tracked. Calling the Load() method again doesn't update the items that are tracked but are not marked as changed, which are already loaded.

What is the preferred method of reloading the preloaded items in a DbSet<>? Off the top of my head, I can only think of calling SaveChanges(), then go through all entries and set both tracked and original values to the current values in the database, then Load() whatever new objects that might have been added. In my scenario it's not possible to delete objects, but I might have to support item deletion in the long run. This doesn't seem right, there should be a way to drop everything and reload. It would seem that it's easier to drop my context and just start anew, but all the elements in WPF are already bound to the Local´ObservableCollection<>, and this just messes up the interface.

Gleno
  • 15,466
  • 11
  • 59
  • 81

4 Answers4

25

This is not the way you are supposed to use DbContext, and because of that it is almost impossible to reload the data. Keeping a single context around for a long time is incorrect usage. The link will also answer why your tracked entities are not updated.

You can selectively reload a single entity by calling Reload on DbEntityEntry:

context.Entry(entity).Reload();

You can also revert back to ObjectContext and use ObjectQuery with MergeOption.OverrideChanges, or use Refresh for a collection of entities with RefreshMode.StoreWins.

All these approaches suffers some problems:

  • If the record is deleted in the database, it will not be removed from the context.
  • Changes in relations are not always refreshed.

The only correct way to get fresh data is Dispose the context, create a new one and load everything from scratch - and you are doing this anyway.

Community
  • 1
  • 1
Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654
  • Thank you for your reply, I am somewhat lost though, because I've read that the exact opposite is preferred in my scenario. I will review these topics, and come back. – Gleno Apr 27 '11 at 19:42
  • I will have no changes in relations, and no deletions in the database. I'll start another question later today, and try to explain why exactly I can't have a short lived DbContext. I really hope you can weigh in with some valuable input. – Gleno May 09 '11 at 10:19
8

With Entity Framework 4.1, the recommendation for WPF data binding has changed to use .Local and a persistent DbContext.

http://blogs.msdn.com/b/efdesign/archive/2010/09/08/data-binding-with-dbcontext.aspx

It's, of course, possible to dispose of it whenever you need to, but it can negatively impact the UI if you do.

Here's another method, but I'm not sure that it takes EF4.1's features into account:

http://msdn.microsoft.com/en-us/library/cc716735.aspx

skst
  • 514
  • 8
  • 14
  • 4
    Thank you very much, I am very confused about the whole .Local thing. Everyone and their dog is telling me not to use a single DbContext for whatever reason, yet it clearly provides this .Local property for long-term binding. – Gleno Jun 30 '11 at 17:08
  • 1
    @Gleno I totally agree with you, IMHO most people use this for ASP in which the context is short lived, but for desktop apps it's just nonsense to reload everything you enter a new form, specially if the info is shared through various forms of your app. – Hannish Sep 27 '13 at 12:37
1

DbContexts are supposed to live short time, Consider after saving changes disposing it and reloading all from the start. Have 2 sets of objects.. one from db and another for binding.

Alexander Taran
  • 6,549
  • 2
  • 37
  • 59
  • 5
    I can't really do this, because then I will lose UI state in the progress. I really wish I could have a short lived DbContext, but I don't see how it's possible in my scenario. – Gleno May 09 '11 at 10:16
0

Please use using() for CRUD.It will automatically reload the updated data.

using (myDbContext context = new myDbContext())
{

}

Best Regards, Thet Tin Oo

Kampai
  • 21,517
  • 19
  • 87
  • 90