How to delete related data with no foreign key using Entity Framework Core - sql-server-2012

I wish to use this in my database context class:
OnDelete(DeleteBehavior.Cascade)
But it's on a SQL Server table with no foreign key.
My parent table, TransplantList, has a column heartId, which corresponds to a table HeartList which looks like this in SQL Server:
heartId
heartName
heartLocation
heartType
TransplantList can only have one heartId per row.
When I delete a row in TransplantList, I also want to delete (if it's not NULL) the heartId associated with it.
I tried adding this to my context database:
Entity.OnDelete(DeleteBehavior.Cascade);
But that just gives me an error.
Is there anyway to do this?
Thanks!

Entity Framework core cannot cascade delete child data for you if the parent and child tables don't have any relationship and foreign key. So you have to get child data manually before deleting child and parent data.
var heart = context.Hearts.Where(x => x.HeartId == transparent.HeartId).FirstOrDefault();
if (heart != null)
context.Hearts.Remove(heart);
context.Transparents.Remove(transparent);
context.SaveChanges();

The Cascade operation is not a part of Entity Framework. It only defines it. The operation itself is performed solely by the database server based on the foreign-key relationship. If your database doesn't define that relationship, there's nothing Entity Framework can do.
As for -
How to delete related data with no foreign key using Entity Framework
Core
check if a related entity exist. If it does, delete it -
var transplant = await context.Transplants.FindAsync(id);
if(transplant != null)
{
context.Transplants.Remove(transplant);
// check if heartId column has a non-null value
if(transplant.HeartId != null)
{
// query the Heart entity with heartId
Heart heart = await context.Hearts.FirstOrDefaultAsync(p => p.HeartId == transplant.HeartId);
// if a Heart entity is found, Delete it
if(heart != null)
context.Hearts.Remove(heart);
}
await context.SaveChangesAsync();
}

Related

Error Deleting a child object from its parent

I'm using vb.net 2013, Entity Framework 6 and SQL Server 2008 R2.
I'm trying to delete from child entities, and this does not work. But if I try to delete directly from context, this works.
In my database I have 2 tables Students and Result.
This is my code that does not work :
Dim context as Myentities = New myentities.
Dim s as student.
Dim lresult as new list (of result)
s = context.students.where(Function(t1) t1.value>5).Tolist.first
lresult = (from t in s.results where t.vl2=7 select t).Tolist
for each rs as result in lresult
if rs.vl3=11 then s.results.remove(rs)
Next
Context.SaveChanges
This code produces an error on the last line (context.SaveChanges) :
An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll
Additional information: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
But if I change the line that delete the item, like below, it works :
Dim context as Myentities = New myentities.
Dim s as student.
Dim lresult as new list (of result)
s = context.students.where(Function(t1) t1.value>5).Tolist.first
lresult = (from t in s.results where t.vl2=7 select t).Tolist
for each rs as result in lresult
if rs.vl3=11 then context.results.remove(rs)
Next
Context.SaveChanges
Why does my first snippet of code not work?
I guess you defined the relationship between Students and Results by adding a Foreign Fey from Results to Students, a non-nullable field named StudentId or similar. When you do the Remove from the parent Student collection of Results, EF does not really remove the deleted Result from the context, EF just removes the relationship between them and sets the StudentId value in your Result child as null, but the child remains in the context. So you get an orphaned child that can't be saved because the FK field is null.
The problem is that your relationship conceptually is an Identifying relationship, which means that you can't have a Result that does not belong to a Student. But EF sees your relationship as non-identifying.
You have two options:
Make EF recognize the relationship as an Identifying relationship, by adding the Foreign Key field StudentId to the Primary Key of Results. You will have a composite key. This way EF will take care of removing the child from the context when you remove it from the collection in the parent.
Leave the PK as is, and explicitly remove the child from the context before saving. That is, you do both the Removefrom the parent collection and the context.Remove.
Usually the second option is preferred because composite keys are a bit complicated to deal with in EF. You can write a method to encapsulate the two operations that should go together every time you delete a Result from a Student.
More info about Identifying relationships here.

Update field(property) in entity

Have i any way update only some fields in my entity?
For example, i want update field Name in entity man, whithout sending full entity.
Now to change the entity I first requested it and after changing the fields, I send this entity to update.
Yes, you can update the entity without updating other properties, by using the Merge Entity or Insert or Merge Entity operation.
Please see our samples for Table storage here. They show how to merge an entity using one of our client libraries.
Here's an excerpt from the .NET sample that may be helpful:
// Create an instance of a customer entity. See the Model\CustomerEntity.cs for a description of the entity.
CustomerEntity customer = new CustomerEntity("Harp", "Walter")
{
Email = "Walter#contoso.com",
PhoneNumber = "425-555-0101"
};
// Demonstrate how to Update the entity by changing the phone number
Console.WriteLine("2. Update an existing Entity using the InsertOrMerge Upsert Operation.");
customer.PhoneNumber = "425-555-0105";
customer = await InsertOrMergeEntityAsync(table, customer);
Also, see the REST API reference for the Merge Entity and Insert or Merge Entity operations:
https://msdn.microsoft.com/en-us/library/azure/dd179392.aspx
https://msdn.microsoft.com/en-us/library/azure/hh452241.aspx

Can't cascade delete or update in Nhibernate if several Entities has references to the same source

I have such mapping of ChargeOperations(left table) and Distributions(right table):
In code mapping of ChargeOperations looks like:
HasMany(x => x.Distributions).Table("ShadowDistributions").KeyColumn("SourceId").Cascade.All().Inverse();
ShadowDistributions - is a right table. x.Distributions is a just a list of Distributions(right table). X - is ChargeOperation(left table)
Mapping of Distributions (right table)
References(x => x.Source).Nullable().Column("SourceId").Not.LazyLoad();
References(x => x.Dest).Nullable().Column("Dest").LazyLoad().Fetch.Join().Cascade.All();
So, I want to delete just one row from Distributions (right table).
And the applications throws different mapping exceptions like "Transaction could not commit because of a failed resource : deleted object would be re-saved by cascade (remove deleted object from associations)[ChargeOperation#58]"" or "Unexpected row count: 0; expected: 1" and so on.
I use cascade for creating entities and it works great, but for delete I had to
clean all references in the right table, and after that save all types of entities separately. If not, I'll get errors.
But I'd like to use cascade saving. How can I realize it?
Possible variants after save:
deleted just one record from right table. all records in left
table are exist
deleted just two records from right table. all
records in left table are also deleted
Change your Cascade to Cascade.SaveUpdate() if you don't wish to delete any of the referenced entities.
In my opinion you shouldn't be trying to delete a parent (ChargeOperations) whenever you delete one of the children (Distributions)
Example
public SomeMethod()
{
using(ISession session = ... //Get my session from somewhere)
{
Distribution childToDelete = ... //Get the distribution to delete
ChargeOperation parent = ... //Get the parent of the distribution we are deleting
parent.Distributions.Remove(childToDelete);
//Since the parent is in session just flush the session to apply changes
session.Flush();
}
}

Entity Framework 4, POCO, WCF, Updating Many-To-Many

I've got a many-to-many relationship mapped in my Entity Framework POCO classes. In the database it's a join table with a composite key, and the POCO properties are generated fine.
When I load an entity from the context, I can remove an item from the many-to-many collection and the database is updated when I save changes.
For Example:
var item = context.Items.First();
item.OtherItems.Remove(item.OtherItems[0]);
context.SaveChanges();
However, when the detached object graph comes back from WCF, I attach it to the context and mark it as modified. But the changes are not persisted.
Example:
// this happens on the silverlight client
item.OtherItems.Remove(item.OtherItems[0]);
// and on the server
context.Items.Attach(item);
context.ObjectStateManager.ChangeObjectState(item, EntityState.Modified);
context.SaveChanges();
In this case the record is not removed from the join table in the database. Any ideas how I can get this to work? Thanks very much in advance.
Changing object state marks your entity modified. You need to use ChangeRelationshipState to mark modified relation between two entities - this will perform DB modification on your join table. You will need to set relation's state as Added or Deleted.

Restricting deletion with NHibernate

I'm using NHibernate (fluent) to access an old third-party database with a bunch of tables, that are not related in any explicit way. That is a child tables does have parentID columns which contains the primary key of the parent table, but there are no foreign key relations ensuring these relations. Ideally I would like to add some foreign keys, but cannot touch the database schema.
My application works fine, but I would really like impose a referential integrity rule that would prohibit deletion of parent objects if they have children, e.i. something similar 'ON DELETE RESTRICT' but maintained by NHibernate.
Any ideas on how to approach this would be appreciated. Should I look into the OnDelete() method on the IInterceptor interface, or are there other ways to solve this?
Of course any solution will come with a performance penalty, but I can live with that.
I can't think of a way to do this in NHibernate because it would require that NHibernate have some knowledge of the relationships. I would handle this in code using the sepecification pattern. For example (using a Company object with links to Employee objects):
public class CanDeleteCompanySpecification
{
bool IsSatisfiedBy(Company candidate)
{
// Check for related Employee records by loading collection
// or using COUNT(*).
// Return true if there are no related records and the Company can be deleted.
// Hope that no linked Employee records are created before the delete commits.
}
}