Reputation: 20057
I have an EF model which enforces a user
> address
one to one relationship which trimmed down looks like this:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int AddressId { get; set; }
[ForeignKey(nameof(AddressId))]
public Address Address { get; set; } = new Address();
}
public class Address
{
public int Id { get; set; }
}
I'm using the a generic repository pattern but the same thing happens if I work directly on the EF context.
If I do this:
public void Create()
{
var user = new User();
context.Users.Add(user);
context.SaveChanges();
}
I get a user created in my DB with an attached address
and both the AddressId
and Address.Id
property are set to a correct value.
However if I do this:
public void Update(int userId, String name)
{
var user = context.Users.Single(x => x.Id == userId);
user.Name = name;
context.SaveChanges();
}
When I look at the user after the SaveChanges()
the name updates as expected but I have an entirely new Address
record created in the DB and EF has incremented the AddressId
property for the user to the new Address.Id
.
This seems like I've made a basic error either in the schema definition, or in how I'm expecting things to work.
Can anyone shed any light on this? appreciate any thoughts.
EDIT
If I make the AddressId
on the User
a nullable int and then tweak the create method like this:
public void Create()
{
var user = new User();
var address = new Address()
context.Addresses.Add(address);
user.Address = address;
context.Users.Add(user);
context.SaveChanges();
}
Then things work as I'd expect.
Upvotes: 1
Views: 578
Reputation: 13498
I think the problem at this row: public Address Address { get; set; } = new Address()
- each time, when EF retrives User
from database, it rewrites old Address
to completely new one, that is why AddressId
is changed and icremented. So, simply remove new Address()
, EF will have done all work by itself:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int AddressId { get; set; }
//[ForeignKey(nameof(AddressId))] is redundant
public virtual Address Address { get; set; }// = new Address();
}
public class Address
{
public int Id { get; set; }
public virtual ICollection<User> Users {get;set;}
public virtual ICollection<Organization> Organizations {get;set;}
}
Usage with not nullable AddressId
:
public void Create()
{
var address = new Address()
context.Addresses.Add(address);
context.SaveChanges();
var user = new User{ AddressId = address.Id };
context.Users.Add(user);
context.SaveChanges();
}
Upvotes: 2