Im making .net application as a project on my Univeristy and I have a problem with Self-Tracking Entity Sets. I'm selecting an record, passing it through a wcf service, make some changes and pass it to the server again. There I want to compare what was changed, so Im selecting the same record from context once a again (this is the record with old values) and comparing. Then, after comparing I want to call ApplyChanges on context with entity passed via the service, and Im getting an error:
AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.
I suppose it's because loading the same entity twice (before changes and after changes to compare). Is there any better way to compare changes(I need to make change history in another db table)? And wouldnt this error also apear if two clients gets the same record, and the first one changes it and wants to store into db? Im using .net 4.0.
This is not supposed way to use STEs. STEs wrap a lot of logic but they are not able to handle duplicate keys attached to context.
So I can imagine two solutions:
Do not load entity for comparing changes. Instead apply changes from your STE and handle SavingChanges event (or override SaveChanges on context) to get applied changes from ObjectStateManager.
Try to detach loaded entity before you apply changes from STE.
Related
I want to add or update entities in EFCore 5.
Currently I am using Context.Find to determine whether to update or to add. I want this logic to be very performant and I see that much of cpu time is spent on the Find method (database call). I would like to move the logic of determining add or update to be evaluated by the database once SaveChanges is called. I would like to be able to specify which properties have changed and which should be used by the possibly already existing entity (or initialized with default values). I guess this can be done with Context.Entry(...).Property(...).IsModified.
I still want to be able to use the DbContext change tracking, multiple add or update calls should be combined, custom queries are not possible.
Primary keys are defined and not auto generated.
Is there any way to achieve this with EntityFrameworkCore?
There is/was IDbSetExtensions.AddOrUpdate but I think it is not available in current release? Also I think it is not recommended to use outside of migrations/seeding. Moreover I think it does not work as I guess it would overwrite existing values with default values of the changed entity (unchanged values should not be overwritten to default values, I am not recreating the complete entity on upsert, thats why I would like to specify which properties have changed).
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.
I have this situation: I'm developing a software with Spring.net and Fluent NHibernate, and I noticed something very unusual with NHibernate's behavior. I really don't know whether it's correct or not, but for my software it cannot happen. I noticed that NHibernate is calling twice all the getters, even when I'm updating something on the database. For exemple, when I try to insert some values on dabatase, NHibernate gets the value from the property to put on database, and then it triggers a new get again, which I don't know why and how is called. I think it tries to retrieve the value from cache to compare both values (database and cache) and save the updated value on cache.
By the way, for some entities I have a secondary cache level, but this situation happens with entities that have and don't have this secondaty cache level.
Any help? Thank you.
You should be able to find it out using print of current stack track
in particular getter and compare it to other traces. This should
show you starting point.
What get into my mind:
Backward get for caching because of second level cache as it stores properties of entities only.
What about has-code computing? Is it use properties to or fields?
Verification whether object in session is as same in the database.
If with get you mean NHibernate runs a select on the database to retrieve the object, within an insert/update this will be done only if you provide the ID of the object and the object is not already available within the session.
If you don't have the object in the database and want NHibernate to insert a new one, do not provide an ID and configure the generator of your ID map correctly
Otherwise make clever use of proxies and prevent NHibernate to retrieve the full object by using Load<T> which will not actually hit the database but puts a proxy into the current session scope.
Problem case:
My problem is editing disconnected POCO entities and then saving them to the database (Uisng Entity Framework). When doing so, the generated sql updates ALL properties even though only some have actually changed. When I do the same within the context, the generated sql correctly updates only the modified properties. This causes problem with my auditing code since it wrongly stores changes on all the properties. This is made worst when the entity I am persisting has a complicated model with many relationships.
My proposed solution:
Instead of attaching the modified entity to the context, I want to query the entity and then manually syncronize the two object with a generic method that will work for any model. So I need to compare all properties from each object and update the modified properties to the attached entity. How do I go about updating the values in the properties, keeping in mind that changes might include new or modified relationships ?
Any thoughts?
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