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.
Problem Description
The error quoted above happened to me after I started using AutoMapper on my WCF service for updating my entities. Previously, I had a "manual map" to passing the properties that I received on my data contract to the entity that I got on my context and update it. When we decided to implement AutoMapper on our project, my mapping code started like this:
Mapper.CreateMap<MyDataContract, MyEntity>.IgnoreAllNonExisting();
Since all my properties were named the same on both classes, everything seemed to be easy peasy.
But sadly, I started getting the error message:
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.
This message was driving me crazy, because of the text I was thinking that I was making something wrong with the FK relationships on the Database, or in someway the field was being passed null
without being null
on the contract, or somebody changed the table in someway (yeah sure, blame others :-P). After some deep look into the code (including debugging line by line all the updating process), I found the error.
Since I'm copying the modified values (from DataContract to Entity) when mapping, I'm passing all the values from one instance to the other. This sounds OK, right? I mean, I want all my changes to be persisted on the database.
Well, is not that easy. Since my contract comes from a web application, when saving there I don't have all the navigation properties. When this is the case and I just map all, I'm also mapping and overwriting the values of this navigation properties, that in this case are null
on my DataContract
. This makes the Entity to update the ForeignKey
Columns that belong to that navigation property to be null too. That is why the error says that you're sending null
values, because actually you are.
Solution
Since the problem is that we're mapping null
navigation properties, and we actually don't need them to be updated on the Entity since they didn't changed on the Contract, we need to ignore them on the mapping definition:
ForMember(dest => dest.RefundType, opt => opt.Ignore())
So my code ended up like this:
Mapper.CreateMap<MyDataContract, MyEntity>
ForMember(dest => dest.NavigationProperty1, opt => opt.Ignore())
ForMember(dest => dest.NavigationProperty2, opt => opt.Ignore())
.IgnoreAllNonExisting();
And voilĂ ! the problem is solved.