Andrian Durlestean
Andrian Durlestean

Reputation: 1730

EF one to one relation change entity with another (substitute)

I have problem to change entity one to one with another:

Here is my test classes:

public class MyUser
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public virtual MyAddress MyAddress { get; set; }
}

public class MyAddress
{
    public Guid Id { get; set; }
    public string AddressLine { get; set; }
    public virtual MyUser MyUser { get; set; }
}

Here is my mapping:

modelBuilder.Entity<MyAddress>().HasOptional(x => x.MyUser).WithRequired(x => x.MyAddress);

In DB i have

MyUser ID = "abc", Name = "Test"
MyAddress ID = "abc", AddressLine = "TestAddress"
MyAddress ID = "dfg", AddressLine = "TestAddress2"

No I want to remove from MyAddress from MyUser where they have same ID, and to add to MyUser a MyAddress that has other ID

// myUser.Id = "abc" myUser.MyAddress.Id = "abc"
// myOldAddress.Id = "abc" myOldAddress.MyUser.Id = "abc"
// myNewAddress.Id = "dfg" myNewAddress.MyUser = null
var myUser = repoUser.GetById("abc")
var myOldAddress = repoAddress.GetById("abc");
myOldAddress.MyUser = null;
var myNewAddress = repoAddress.GetById("dfg");
myUser.MyAddress = myNewAddress;
myNewAddress.MyUser = myUser;
//on save I have this exception and what result i want to have
// myUser.Id = "abc" myUser.MyAddress.Id = "abc"
// myOldAddress.Id = "hjk" myOldAddress.MyUser = null
// myNewAddress.Id = "abc" myNewAddress.MyUser.Id = "abc"
// something like this (substitute)

Exception:
Additional information: A referential integrity constraint violation occurred: 
A primary key property that is a part of referential integrity constraint cannot be 
changed when the dependent object is Unchanged unless it is being set to the
 association's principal object. The principal object must be tracked and not
 marked for deletion.

{"A referential integrity constraint violation occurred: A primary key property
 that is a part of referential integrity constraint cannot be changed when the 
dependent object is Unchanged unless it is being set to the association's 
principal object. The principal object must be tracked and not marked for deletion."}

Why EF doesn't change ID automatically to be the same as UserId? User must have Address 1:1, but Address has optional User 1:0

Upvotes: 2

Views: 4789

Answers (2)

Muhammad Gouda
Muhammad Gouda

Reputation: 869

First, I am not convinced with the design where relation between User and Address is one-to-one, neither allowing addresses without users while not allowing users without addresses. Because usually a typical user can has many addresses


However, as per our discussion in the comments section, I got the following:

Your Address table in database has 2 columns: ID that does not allow null and AddressLine

So, when you call myOldAddress.MyUser = null; in your code You simply till EF to set Address.Id to null in database which violate the DB constraint

One solution, that I don't recommend is to let Address.Id to allow null

But I recommend to change the design to one of the following:

  • Identify your address table with a separate unique key other than UserId
  • create a column to hold the related userId and make it allow null

So your Address table will be as follows:

ID (not null)
AddressLine 
UserId (Nullable) forieng key in User Table

This way you can set MyAddress.MyUser to null in your code, safely

Upvotes: 3

dipole
dipole

Reputation: 439

From the code samples, myOldAddress.MyUser property is currently not set. Can you try commenting that line out

var myUser = repoUser.GetById("abc")
var myOldAddress = repoAddress.GetById("abc");
//myOldAddress.MyUser = null;
var myNewAddress = repoAddress.GetById("dfg");
myUser.MyAddress = myNewAddress;

Since user field is optional on the address entity, if you did not set it before, there is no need to set it to null.

Upvotes: 0

Related Questions