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.
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.
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
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.
Please use using() for CRUD.It will automatically reload the updated data.
using (myDbContext context = new myDbContext())
{
}
Best Regards,
Thet Tin Oo
Related
The Problem
We have an app that stores hierarchical data in a database. We have defined a POCO object which represents a row of data.
The problem is we need certain properties to be dependent on the item's children and others on their ancestors. As an example, if a ((great)grand)child has incomplete state, then implicitly all of its parents are also incomplete. Similarly, if a parent has a status of disabled, then all children should be implicitly disabled as well.
On the database side of things, everything works thanks to triggers. However, the issue we're having is then synching those changes to any in-memory ORM objects that may have been affected.
That's why we're thinking to do all of this, we need to ensure there is only ever one model instance in memory for any specific row in the database. That's the crux of the entire problem.
We're currently doing that with triggers in the DB, and one giant hash-set of weak references to the objects keyed on the database's ID for the in-memory ORM objects, but we're not sure that's the proper way to go.
Initial Design
Our 'rookie' design started by loading all objects from the database which quickly blew out the memory, let alone took a lot of time loading data that may never actually be displayed in the UI as the user may never navigate to it.
Attempt 2
Our next attempt expanded on the former by dynamically loading only the levels needed for actual display in the UI, which greatly sped up loading, but now doesn't allow the state of the hierarchy to be polled without several calls to the database.
Attempt 2B
Similar to above, but we added persistent 'implicit status' fields which were updated via triggers in the database. That way if a parent was disabled, a trigger updated all children accordingly. Then the model objects simply refreshed themselves with the latest values from the database. This has the down-side of putting some business logic in the model layer and some in the database triggers as well as making both database writes and reads needed for every operation.
Fully Dynamic
This time we tried to make our models 'dumb' and removed our business layer completely from the code, moving that logic entirely to the database. That way there was only single-ownership of the business rules. Plus, this guaranteed bad data couldn't be inserted into the database in the first place. However, here too we needed to constantly poll the database for the 'current' values, meaning some logic did have to be built in to know which objects needed to be refreshed.
Fully Dynamic with Metadata
Similar to above, but all write calls to the database returned an update token that told the models if they had to refresh any loaded parents or children.
I'm hoping to get some feedback from the SO community on how to solve this issue.
Im running a process that will affect a lot of records within a database for a user. I only want to apply all of the changes or none of them depending on the result of all of the changes. (e.g if one of the sub processes fail then no changes overall should take place). I also want to save notifications to the database to alert users of the outcome of the processes (e.g if a sub process fails then a notification is raised to let the user know that no changes were made due to reason x).
The best way I can think to do this is to detach all of the entries within the change tracker as they are added, then create notifications if something has succeeded or failed and save changes, then when it comes to applying all the changes I can iterate though the change tracker and reset the Entity State and save changes once more.
The issue i'm facing with this approach is that when it comes to reset the Entity State, I don't know whether the entity is Added or Modified. I could implement my own change tracker to store the previous state of the entity but it would make EF's change tracker redundant.
I could also only add all of the entity's right when I come to save them but that would require passing many objects down a chain link of nested methods right until the end.
Does anyone have any better suggestions or is it standard practice to use one of the mentioned hacks for this problem?
It sounds like you are trying to implement the Unit of Work pattern. The DbContext of EntityFramework makes this fairly easy to use, as the DbContext its self is the unit of work.
Just instantiate a new context and make the changes you need to it. You can pass the context around to any functions that make their changes. Once the "logical unit" operations are complete, call SaveChanges. As long as the individual methods do not call SaveChanges, you can compose them together in to a single unit, committed once the entire logical operation as finished. Everything will be committed atomically, within a single transaction. The data won't be left in an inconsistent state.
You told about transactions. Using Transactions or SaveChanges(false) and AcceptAllChanges()?
also you can implement versions of data in DB. as for me it will be more ease and correct way (you must always only insert data and never update. 1-to-many). in this case you can simply delete last records or mark them as unactive
This has probably already been asked and answered 1000 times, but Google has not been not my friend this morning.
I'm making the switch from using stored procedures and business objects to using Entity Framework. I like the simplicity of generating your POCOs from the generated EDM (Database-First approach here). And I like how much less typing it is.
I'm having a hard time wrapping my head around a suitable design for a VERY COMMON application scenario (in my world, anyway).
Basically, picture a data entry application, let's say for an online store's administrator (I'm doing it in WPF, but it could easily be web-based).
The admin will want to view a list of Customers (Manage Customers view) in a data grid. For each row, there is button to edit the Customer or delete it. At the bottom of the grid there is a button to create a new Customer.
If they delete a Customer, it is removed (after a confirmation) immediately from the data grid, as well as the back-end data store. If they edit a Customer, a window pops up (Edit Customer View), displaying the current data for that Customer. They can edit the data, then click either Submit, or Cancel. Submit saves the changes to the data store, and cancel discards the changes. Both buttons close the Window.
If, they click the New Customer button from the Manage Customer view, then a new Customer object is created (not saved to the DB yet), and the same Edit Customer view is opened, displaying the new, blank Customer.
Here is what I've got so far:
When the Manage Customers View Model is constructed, it populates a public list of Customers, something like:
public List<Customer> customers {get; set; }
using (WebStoreEndities context = new WebStoreEntities())
{
customers = context.Customers.ToList();
}
Then, if the admin user clicks the Edit button in a Customer row, the bound Customer object is passed to the constructor of the Edit Customer view. That view constructs its view model, which has the customer property that the view is bound to. The user can make their changes to the Customer object in the view, then either click Save or Cancel.
This is where I get lost. In my business object/stored procedure implementation, I would just have two Customer objects: one for the Customer being edited (bound to the view), and one copy of that Customer, called backupCustomer, used for reverting changes if they cancel out of the Edit Customer view (since I'm using MVVM, the properties of the Customer are changed immediately from the UI, and if they start making changes, and then click Cancel, they'll expect not to see their changes in that Customer).
More to the point, if they do click Submit in the Edit Customer view, that calls the Customer business object's Save() method, which reaches into the DAL and fires off the stored procedure to update the data store.
Okay, so now on to Entity Framework reality.
Issue #1. There is no way to save an individual entity. So even if I extend the Customer entity to have a Save() method, it would have to create a new WebStoreEntities context and call SaveChanges() on it:
using (WebStoreEntities context = new WebStoreEntities())
{
context.SaveChanges();
}
That seems weird to me. I wouldn't think you'd want have an entity instance creating entity contexts and stuff.
Issue #2. In my business objects implementation, I cache my objects, so I only need to ever fetch them from the DB once. If they make changes to a Customer, great. I just call save() on it and it updates the data store. Same with deletes and inserts. But I never have to fetch the same collection of Customers more than once (concurrency is not an issue on this particular project). In my EF implementation, every time they open the Manage Customers view, it's firing off the code above to get a list of Customers. I suppose I could just keep one data context open during the entire application, but that seems like a bad design too. Tying up a connection the the data store for the entire user session, just because they might open the same view more than once.
Please help me with my above issues, if you can, don't get hung up on what I'm about to say (it's just my initial impression anyway):
It seems like EF muddies the logical boundaries in my separation of concerns:
You have to keep a copy of the Entity connection string in your UI project (I keep my business objects and data objects in a separate project usually).
You can't tell an entity to save itself or delete itself. You have to do it from the underlying context, which is typically in the UI layer. In my UI, I like to be able to say myBusinessObject.Save() or myBusinessObject.Delete(), knowing that the object knows how to save or delete itself.
Anyway, it seems like EF is the future, so I'm going to stick with it. I would love your recommendations.
Thanks so much!
The Funk Monkey.
While most examples have you implement queries surrounded by a using you shouldn't actually do that in your case. Each EF context tracks it's own entity changes, by using multiple usings you won't know which context did the look up to call SaveChanges on it. So just use one context per user and dispose when your completely done (on exit, ect). You can use a singleton or a static class, in a desktop app it doesn't seem to make much difference from my experience. In an MVVM scenario you may be able to get away with the ViewModel handling the context as well, so when you instantiate your ViewModel instantiate your context and dispose your context on dispose, that might make more logical sense depending on how your handle the data internally.
For being able to revert changes EF actually tracks both the original DB version of the object as well as your changed version of the object. However to get that information is a little convoluted:
Disconnect and look up the entity:
((IObjectContextAdapter)myContext).ObjectContext.Detach(dbObject);
var entry = myContext.Entry(dbObject);
var original = entry.OriginalValues;
Personally I just handle copying and keeping the original object in code, it's cleaner and seems to be safer. It's also probably faster, but I've never run tests to prove that. If you're in a multi-user environment you may benefit from simply reloading the data from the DB though so that you don't mistakenly display stale data.
Issue #1: You want you entity to have a Save method but you want to avoid creating a coupling between the entity and the persistence layer (e.g. the EF context)? Well, if the Save method is implemented by the entity then you cannot avoid that. Better perhaps, is to move the Save method to a repository:
repository.Update(entity);
Now it is the responsibility of the repository to create the EF context, not the entity.
Issue #2: EF contexts are lightweight and the normal pattern of usage is as you describe where the context is created transiently and then disposed after changes have been saved. Conceivably, you can create a desktop app the has one context for the lifetime of the application but if the database is changed while the app is running the content of the context will get out of date. Sooner or later inconsistency in state will hit you and I would think that you get a more maintainable application if you stick to the transient context pattern. If you are writing a web app you will not have the option to keep a database context alive between requests and that pattern has proven to be very successful when writing business apps.
So I recommend this:
Implement persistence in a repository or service class, not in the entity class.
When reading or writing entities do it in a manner that ensures that the EF context only exists for the duration of the operation (unit of work). Optionally, you can use a row version number to ensure that an entity cannot be updated if it has been changed in the database after the last write.
By the sounds of it...you prefer the ActiveRecord pattern...but EF follows the UnitOfWork pattern...in your case you are using POCO Entities....which are "persistent-ignorant".
http://randolphcabral.wordpress.com/2008/04/03/active-record-vs-unit-of-work/
refactoring: swicthing from custom data access layer to Entity Framework
One approach to hide the "EF technology", is to create a "repository" layer inside of which you hide all the EF logic i.e. management of the "context". But creating another layer can be a lot of repetitive work. Typically your repositories would share the same context.
http://blogs.msdn.com/b/wriju/archive/2013/08/23/using-repository-pattern-in-entity-framework.aspx
http://www.dataworks.ie/blog/entity_framework_5_with_automapper_and_repository_pattern
If you keep the EF context around, then it manages the change-tracking and caching of already retrieved objects for you.
Alternatively, you can work in a disconnected mode...where you create the context each time you want to retrieve/perist entities...however, you then have to do the caching and state-tracking yourself and "reattach" the objects to the context, before submitting.
I'm working on a WP7 mango App that makes use of Linq2SQL for data access.
I'm having a Note entity that has an Auto generated Key of type int.
The first time I add a new note to the db, the operation works fine, the note saves and then if I delete it from the db, it also gets removed from the db. The first entity is always of Id=0.
Then if I want to add a new note after removing the first note, I get an exception saying that the entity already exists. I concluded that the first entity with Id=0 has not been removed even though I called SubmitChanges on my data context.
Also, I'm using the same data context for data operations on my repository and on the same repository instance (a singleton for performance reasons).
To confirm that behavior, I tried to make the succession of calls and it failed !!!
this.DbContext.Notes.DeleteOnSubmit(value);
this.DbContext.SubmitChanges();
this.DbContext.Notes.InsertOnSubmit(value);
this.DbContext.SubmitChanges();
It says that it cannot add an Entity that already exists.
Any explanation for this behavior?
Thanks in advance.
Note :
When I use two different instances of the data context, this behavior disappears.
Well You answered your own question really at the end. Lets step through this:
You get the DbContext from the Database
Your Deleting an entry and submitting the Database(OK fine)
Now on this insertion your using an OLD instance of the database.
Everytime you make a
SubmitChanges();
You have update your reference, because its old.
So if you have a method that does multiple Transactions you NEED to refresh your local variable.
ONE instance of a Database should do ONE change
I'm using .NET entity framework 4.1 with code-first approach to effectively solve the following problem, here simplified.
There's a database table with tens of thousands of entries.
Several users of my program need to be able to
View the (entire) table in a GridRow, which implied that the entire Table has to be downloaded.
Modify values of any random row, changes are frequent but need not be persisted immediately. It's expected that different users will modify different rows, but this is not always true. Some loss of changes is permitted, as users will most likely update same rows to same values.
On occasion add new rows.
Sounds simple enough. My initial approach was to use a long-running DbContext instance. This one DbContext was supposed to track changes to the entities, so that when SaveChanges() is called, most of the legwork is done automatically. However many have pointed out that this is not an optimal solution in the long run, notably here. I'm still not sure if I understand the reasons, and I don't see what a unit-of-work is in my scenario either. The user chooses herself when to persist changes, and let's say that client always wins for simplicity. It's also important to note that objects that have not been touched don't overwrite any data in the database.
Another approach would be to track changes manually or use objects that track changes for me, however I'm not too familiar with such techniques, and I would welcome a nudge in the right direction.
What's the correct way to solve this problem?
I understand that this question is a bit wishy-washy, but think of it as more fundamental. I lack fundamental understanding about how to solve this class of problems. It seems to me that long living DbContext is the right way, but knowledgeable people tell me otherwise, which leads me to confusion and imprecise questions.
EDIT1
Another point of confusion is the existance of Local property on the DbSet<> object. It invites me to use a long running context, as another user has posted here.
Problem with long running context is that it doesn't refresh data - I more discussed problems here. So if your user opens the list and modify data half an hour she doesn't know about changes. But in case of WPF if your business action is:
Open the list
Do as many actions as you want
Trigger saving changes
Then this whole is unit of work and you can use single context instance for that. If you have scenario where last edit wins you should not have problems with this until somebody else deletes record which current user edits. Additionally after saving or cancelling changes you should dispose current context and load data again - this will ensure that you really have fresh data for next unit of work.
Context offers some features to refresh data but it only refreshes data previously loaded (without relations) so for example new unsaved records will be still included.
Perhaps you can also read about MS Sync framework and local data cache.
Sounds to me like your users could have a copy (cached) of the data for an indefinate period of time. The longer the users are using cached data the greater the odds that they could become disconnected from the database connection in DbContext. My guess is EF doesn't handle this well and you probably want to deal with that. (e.g. occaisionally connected architecture). I would expect implementing that may solve many of your issues.