I'm implemented the unit of work like this tutorial explained:
http://www.codeproject.com/Articles/543810/Dependency-Injection-and-Unit-Of-Work-using-Castle
Though now I encounter a strange problem.
I load within a unit of work (in the transaction) an entity from the database
I update a property of that entity
I call not the save method on my repository
The transaction is committed
In this scenario, I would expect that the updated property is not persisted to the database. But it is. So an entity loaded in my session is tracked and committed to the database without calling save. What is causing this? And is there a way to tell Nhibernate not to update those entities if the save is not called?
I realize I can work around this to update only a property when I need to update. The only risk is by accident updating the property by mistake and it is then very hard to find this problem. (and for example someone new, not knowing this could easily make a mistake)
The explanation requires understanding the difference between a transient and a persistent entity. A transient entity is a new entity and it is made persistent by calling Save(). An entity that has been retrieved using NHibernate is already persistent and any changes made to it will be automatically saved when the session is flushed. NHibernate's goal is to make the database consistent with the domain model when the session ends.
See chapter 9 in the documentation.
Related
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
I'm using ASP.NET WebApi 2 and loading in part of a relational database structure into the front end website. This allows the user to make changes to multiple tables in a single store and to also view some extra data.
This mostly works pretty well. It means I can store changes to, say a person table and their related clothes and hair color on one call as follows:
db.person.Add(person);
db.SaveChanges();
The problem is that, I don't want to load all the related data. So where the shoe table may be loaded, I don't want the laces table to load with info about laces.
The issue I'm running into is that there is an attempt to store a duplicate shoe table to the database even though this was only loaded to allow the user to view these details. I imagine that this is because, I'm using [JsonIgnore] attributes to ignore certain parts of the object - it is thus recognizing this as a new object, when it isn't.
I could loop through the object removing any shoe information before call Add, but this would be slow.
Perhaps it is best to post a second object that only includes the items that have changed (after tracking these in the front end). Is there a better way?
When you use DbSet<T>.Add() in EF, the entity (or all the entitis in the tree, if it's an entity with related child entities) is attached to the DbContext as Added. That means that when you call SaveChanges EF will try to insert all the objects in the database. That's why you're getting duplication problems.
You need to learn how to work in disconnected mode with EF. Basically you need to track the state of each entity (i.e. control if they have to be inserted, deleted or updated), and set the correct state when you attach the entities in the context.
Look for docs on working with disconnected entities in EF, for example:
Persistence in Entity Framework
Add, Attach and Entity States
These will explain you how to handle disconnected entities.
The short question is, can I make EF perform an update when the Poco class has a value for the primary key field and an insert otherwise? Exactly the way NHibernate does.
Unless I'm mistaken the EF way is really ugly.
First instead of using .Add(entity) for inserts or updates you .Add for inserts and for updates:
context.MyEntities.Attach(entity);
I tried that but nothing was saved at all. After reading this I saw I was missing setting the changed state? But my context doesn't have an ObjectStateManager so I need something like:
var manager = ((IObjectContextAdapter)dbContext).ObjectContext.ObjectStateManager;
This seems like a very convoluted and inelegant approach to me. Can I make EF work the way NHibernate does? (If not I'm still early enough in the project that I can rip EF out and go back to using NHibernate)
You have to use the context.Add(entity) in order for Entity Framework to know that it needs to track changes on that object. If the entity already exists in the context, EF will automatically track changes to it and push those changes to the database when you call context.SaveChanges().
You are attaching an entity so you should try EntityState = Modified before savechanges.
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 was wondering if it was wise to cache the Entity Framework's ObjectContext object in the Cache; will this give me issues with multiple connections at the same time that the user will experience issues with that?
I've gotten errors like: 'connection is currently closed' and wondered if that was due to multiple users and caching the ObjectContext, or if it was related to say hitting refresh multiple times or stopping the page and quickly doing something else (something that we did do to get the error).
I agree with above. However, I do cache the object context in HttpContext.Current.Items collection without any issues. Also a good read:
http://dotnetslackers.com/articles/ado_net/managing-entity-framework-objectcontext-lifespan-and-scope-in-n-layered-asp-net-applications.aspx
I wouldn't advise it. The ObjectContext needs to be active to observe changes to any entities you are actively working with or you'd need to disconnect any active entities prior to caching the ObjectContext.
If you have no active entities, then there's no real need to cache an ObjectContext. In EFv1 working with disconnected entities was problematic at best, so I'd either not cache or wait for the Entity Framework v4 which allows for more manageable entities (self tracking entities, POCO entities etc).
Just thought I'd add one last point - multiple threads - could be problematic as well. Applying Changes will attempt to commit all changes tracked by the ObjectContext. If multiple users are sharing a single Context... well, hopefully you can see the problems..