Entity Framework delete without select and Optimistic Concurrency - entity-framework

I am trying to delete a record if it exists using Entity Framework - I want to generate something like
delete from tbl where id = 1
I don't care whether any records exist, I just want to delete them if they do. I should be able to do with without selecting them first like this:
var record = new tbl { id = 1, rel = new tbl_related { tbl_id = 1 } };
context.tbl.Attach(tbl);
context.tbl.Remove(tbl);
context.SaveChanges();
The syntax might not exactly be there because this isn't a copy and paste, and I've added the foreign key relationship to show that I'm taking this into account.
On running this code the correct SQL is generated by EF and run but I get a System.Data.Entity.Infrastructure.DbUpdateConcurrencyException saying "Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded".
However, I'm fully expecting zero rows to be deleted a lot of the time. Any ideas on how I can get around this?
I've been pointed to How to ignore a DbUpdateConcurrencyException when deleting an entity as a possible duplicate. This suggests handling the DbUpdateConcurrencyException which I am now doing (and ignoring), but that post talks about trying to delete rows that might have been deleted - I want to delete rows that might never have existed. I know this might just be a question of semantics because the resolution is the same but I want to highlight that I am doing something that I see as perfectly reasonable and the Framework is not handling it very well.
Thanks

There is an extension for EF on github that allows you to update and delete entities with a single call to the database.
With this extension you can do something like this:
context.tbl.Delete(t => t.Id == 1);
A single call should eliminate your DbUpdateConcurrencyException.

Related

Hibernate persisting incorrect values

I have some Hibernate code running against a Postgres 9.5 DB, which looks like roughly like below (anonymized) -
Integer myEntityId = myEntity.getId();
getCurrentSession().evict(myEntity);
myEntity.setId(null);
MyEntity clonedMyEntity = (MyEntity)getCurrentSession().merge(myEntity);
myEntity.setMyBooleanField(false);
getCurrentSession().save(myEntity);
I have an entity myEntity with a large number of fields. I want to create a duplicate of the record with only 1 field value changed. To achieve this, I evict the entity from session, set Primary Key to null, merge it back to session, set the field I want to change, and then save the entity to DB. However, this code (which was working correctly for some time), is not working now. It sees incorrect value for the boolean field I am trying to modify - as a result violating some database constraints. Please help me fix this or suggest a better way to achieve what I am trying.
The error was happening not on adding this record but on add of another record to an audit table, triggered by the addition of this record. A coworker suggested me to use Eclipse Breakpoint view and use the add breakpoint option there and select the ConstraintViolationException class - this helped me to see the error for which trigger was failing and why and accordingly modify the data to suit the database constraint.

Delete link table entry but not referenced table entries

I am using Entity Framework database-first model. I have 2 tables that are referenced by a link table.
For example:
When I update my edmx file from my database this creates the expected model:
Now what I want to do is delete an entry from the Product_User table without deleting the referenced entry in either of the related tables (Product or User).
I've tried both of these statements (together and separately) but neither seems to have any effect:
user.Products.Clear();
foreach (var product in products)
{
product.User = null;
}
Is what I'm trying to do possible with the model the way I have it now? And if so what am I doing wrong?
I noticed I can do what I'm trying to do if I add the link table explicitly to the model but I'm trying to avoid that.
Any help would be much appreciated. Thanks.
Your seconde way to go (with a loop) seems more like the correct way.
Instead of = null try to use the .Remove() function. I guess the remove function only remove the link between the two entity, not the entities related.
See this answer : Removing many to many entity Framework

ASP.NET Core EF DbUpdateConcurrencyException

I was trying to manually implement a cascade delete in my ASP.NET Core website.
So, I got a Poll section which is based on 3 entities: PollQuestion, PollOption, PollAnswer.
I'm starting this by deleting all the answers, and this goes fine, then I move to deleting the options with this code:
if (answersDeleted) {
options = GetOptionsList(_pollID);
context.PollOption.RemoveRange(options);
context.SaveChanges();
return true;
} else {
return false;
}
When the SaveChanges() is executed I get this exception:
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 2 row(s). Data may have been modified or deleted since entities were loaded.
So. I can't really understand why he was expecting to affect 1 row since I pass a list to RemoveRange().
In case someone could make use of this one day.... i found the problem, it wasn't strictly related to the chunk of code i posted; few days ago i modified the poll table, and changed the Key, from a single field key to a composite key, then i forgot to reflect that change in my Model, which still was using a single key. It wasn't returning any error so i didn't notice this until i had to do other stuff on the DB and there i found the problem.

Entity Framework 5 SaveChanges Not Working, No Error

None of the many questions on this topic seem to match my situation. I have a large data model. In certain cases, only a few of the fields need be displayed on the UI, so for those I replaced the LINQ to Entity query that pulls in everything with an Entity SQL query retrieving only the columns needed, using a Type constructor so that I got an entity returned and not a DbDataRecord, like this:
SELECT VALUE MyModelNameSpace.INCIDENT(incident.FieldA, incident.FieldB, ...) FROM ... AS ...
This works and displays the fields in the UI. And if I make a change, the change makes it back to the entity model when I tab out of the UI element. But when I do a SaveChanges, the changes do not get persisted to the database. No errors show up in the Log. Now if I very carefully replace the above query with an Entity Sql query that retrieves the entire entity, like this:
SELECT VALUE incident FROM MyDB.INCIDENTs AS incident...
Changes do get persisted in the database! So as a test, I created another query like the first that named every column in the entity, which should be the exact equivalent of the second Entity SQL query. Yet it did not persist changes to the database either.
I've tried setting the MergeOption on the returned result to PreserveChanges, to start tracking, like this:
incidents.MergeOption = MergeOption.PreserveChanges;
But that has no effect. But really, if retrieving the entire entity with Entity Sql persists changes, what logical purpose would there be for behaving differently when a subset of the fields are retrieved? I'm wondering if this is a bug?
Gert was correct, the problem was that the entity was not attached. Dank U wel, Gert! Ik was ervan verbluft!
I just wanted to add a little detail to show the full solution. Basically, the ObjectContext has an Attach method, so you'd think that would be it. However, when your Entity SQL select statement names columns, and you create the object using a Type as I did, the EntityKey is not created, and ObjectContext.Attach fails. After trying and failing to insert the EntityKey I created myself, I stumbled across ObjectSet.Attach, added in Entity Framework 4. Instead of failing, it creates the EntityKey if it is missing. Nice touch.
The code was (this can probably be done in fewer steps, but I know this works):
var QueryString = "SELECT VALUE RunTimeUIDesigner.INCIDENT (incident.INCIDENT_NBR,incident.LOCATION,etc"
ObjectQuery<INCIDENT> incidents = orbcadDB.CreateQuery<INCIDENT>(QueryString);
incidents.MergeOption = MergeOption.PreserveChanges;
List<INCIDENT> retrievedIncidents = incidents.ToList<INCIDENT>();
orbcadDB.INCIDENTs.Attach(retrievedIncidents[0]);
iNCIDENTsViewSource.Source = retrievedIncidents;

Deleting all related entities in Entity Framework

I have an entity called Entry connected to multiple TimeWindows. I want to clear all time windows, then add new ones. At first I tried:
target.TimeWindows.Clear();
but this didn't really delete them, and only tried to remove the relationship, which caused an exception since there is foreign key from TimeWindows to Entry. Then I thought I should do this:
foreach (var tw in target.TimeWindows)
context.DeleteObject(tw);
but this throw an exception as well, since the collection was modified inside the foreach statement. So I thought of this:
while (target.TimeWindows.Count > 0)
context.DeleteObject(target.TimeWindows.Last());
But now I am a bit concerned about using Count property, because it might cause a SQL SELECT COUNT statement to be executed. Does it? If yes, how can I delete all time windows in Entity Framework?
Calling count on navigation property will cause select only if lazy loading is enabled and the property is not loaded yet. So the first call can cause something like:
SELECT * FROM TimeWindows WHERE TargetId = #targetId
and all count evaluations will just execute on loaded data.
You can also use this to avoid the second exception:
foreach (var tw in target.TimeWindows.ToList())
context.DeleteObject(tw);
Or you can change your database and model to support identifying relation (FK to parent will became part of TimeWindow's PK) and in such case your first code snippet will work.