I have a table named "Notaries":
NotaryID int,
NotaryName nvarchar(MAX)
and table named "NotaryPhones":
PhoneID int,
NotaryID int,
PhoneNumber nvarchar(50)
So, relationship "one-to-many". Now I want to clear all phones, depending on the notary. My code:
Notary.Models.Notary notary = (from i in db.Notaries where i.NotaryID == model.NotaryID.Value select i).FirstOrDefault();
notary.CityID = Convert.ToInt32(model.City.SelectedItem);
notary.NotaryPhones.Clear();
db.SaveChanges();
but I get an error:
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.
If I remove the string
notary.NotaryPhones.Clear();
it works. I understand, that this is a trivial thing, but don't understand how to fix it
What's going on is that your notary.NotaryPhones.Clear(); is removing the foreign-key reference from your NotaryPhone table to your Notary table. Because this is set up as a non-nullable key so that you don't have orphan phone records, you're receiving that error.
What you'll want to do instead is set up a method in your repository that will call context.NotaryPhones.Remove(**instance variable pointing to one of the phones to delete**); and that will delete them from the database.
CLARIFICATION
The reason why it removes the foreign key reference is that notary.NotaryPhones.Clear() just removes those objects from the notary object. The objects will continue to exist the way that you have written this.
So when the .Clear() is executed, it takes your phone.NotaryID property and gets rid of the ID pointer to the notary. Since you're not assigning it anything else, the value it tries to assign is null (the only value that couldn't possibly point to a Notary object). But, because you have it set up as an int, and not an int?, it can't make that assignment and it throws the error you see.
You said you're trying to delete the objects, so you need to remove them from the database. To do that, you do what I explained above.
please excuse the example if there are syntax errors, I am currently working in VB but the approach is the same
foreach (NotaryPhones np in notary.NotaryPhones)
{
db.NotaryPhones.DeleteObject(np);
}
then save your changes with
db.SaveChanges();
Clear just removes entity from the related collection. it doesn't remove entity from database. you have to delete each NotaryPhone from corresponding DbSet.
Related
I am modifiying the foreign key property on an entity in code, by modifiying the Id only:
ElementData.ServiceLevelId = parameter.ServiceLevelId;
I have found, after persisting, that this only works as expected, when the corresponding navigation property ServiceLevel was null by accident. If it still holds the "old" object, the change will not hit the database.
This means, I need to do
ElementData.ServiceLevelId = parameter.ServiceLevelId;
ElementData.ServiceLevel = null; //Force the update to the Database
Does that mean, that changing the object is "stronger" than changing the id only? Should I always set the related object to null in such situations?
Update (per Tim Copenhaver's comment): The entity in question is a copy (with the mentioned modification) of an existing one. It uses Automapper for copying, and maps everything except the primary key and one unrelated property. Automapper creates a shallow copy AFAIK. Thus, the situation for the copy will be that the updated Id and the untouched object reference will not match at the moment of adding it to the context. I guess, that EF then decides that the "object reference is stronger".
Changing either property will work as long as your data mapping is correct. EF is smart enough to see which of the properties has changed and ignore the other one. You have to be careful, though - if ElementData.ServiceLevel.Id does not equal ElementData.ServiceLevelId, you will get some obscure errors.
If you're having trouble with it not saving, your mapping layer is probably not correct. We can help troubleshoot if you can post the mapping for your ElementData class and some more code around how you're doing the save.
Im using EF 6 to build my app. Ive got entity User and entity BoughtProduct
In User:
this.BoughtProducts = new HashSet<BoughtProduct>();
Then I do some logic in my app. Sometimes I do sth like this:
MyUser.BoughtProducts.Clear();
then when I save changes to my context I have following error:
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.
What am I doing wrong?
I have a DBFirst EntityFramework 6.1 solution that i'm trying to generate off of. When i add a table that only contains two foreign keys the table is turned into two associations and I can not directly access the table anymore. This is neat for navigation in the code but makes it a pain in the ass to delete records from the table.
Is there a way to prevent this behavior and gain direct access to the table as an entity?
For example i am unable to remove an entry in the association because i get this error
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.
For example here is how my database sees the structure.
Here is how it appears in entity framework. Notice that the CorporateDataShareVisible table is missing and instead two new associations are created.
The CorporateDataShareVisible table should be able to be deleted and added to at will but any changes i make seem to stop it from working.
Add a primary key to your table that has only foreign keys. EF uses the primary key to keep track internally of the element. Without a primary key it doesnt know which element was modified and how to send that back to your RDBMS.
I prefer surrogate keys i.e auto incrementing integers.
You can also add the primary key by making it a composite key of both the foreign keys
I have an instance of TPM_PROJECTVERSION called projectVersion, which has a property called TPM_USER5 which is of type TPM_USER. A TPM_PROJECTVERSION can have zero or one TPM_USER5 references (Sorry, I didn't come up with these names.)
When the user clicks a Delete button, I want to remove this reference, thus setting the column in the database to null. I've tried the following:
projectVersion.TPM_USER5 = null;
However, when I call context.SaveChanges(), the column is not updated and nothing happens. Under the debugger, I can see that projectVersion.TPM_USER5 is indeed null, and I also see that projectVersion.TPM_USER5Reference.IsLoaded is true. I've also tried:
context.DeleteObject(projectVersion.TPM_USER5);
If I do this, when I call context.SaveChanges(), I get the exception:
{"ORA-02292: integrity constraint
(TPMDBO.TPM_PROJECTCHANGES_TPM_US_FK1) violated - child record found"}
I'd be happy to post more information about the entity mappings, but not sure exactly what's relevant. Any ideas?
If I understand correctly thus you removing only navigation property (TPM_USER5). Try set primitive property (TPM_USER5ID? - probably your db column name) to null.
Each navigation property must have relevant primitive property (not POCO entities) and you can use both to associate user to TPM_USER5 (primitive property - set id, navigation property - set reference).
We would like to implement a simple rule in which NHibernate would assign (persist) NULL to the database when the ID for the entity is equal to -1. For example, we have an "in system" account which should be persisted to the database as NULL.
If we try to persist the ID of -1 to the database we get a Foreign key exception because the ID does not exist in the foreign table.
We are using NHibernate with FluentNhibernate.
I think you didn't a proper mapping of your entity. If it were correct, you should made any trick: you should not see an ID, but a reference to another entity, and in this case you will persist the reference with a null value. Even in the wrong case you want map the entity with a reference expressed as an ID ( that is almost always wrong ) if this id is nullable, map it as a nullable so you have int? and you can fit null to mean null, instead of the -1 trick.
See Comments
If a custom entity is internally used as a null value, a session interceptor could help: working on the OnSave and treat the special case by replacing the dummy entity with null.
Here you can find the documentation about NH interceptors.
At the 11.2 chaper od the same doc there is the portion related to events, equivalents for this kind of problem.