Klasa Entity Object:
public abstract class EntityObject : IEntityObject
{
protected EntityObject()
{
this.State = EntityState.Incomplete;
this.DateCreated = DateTime.Now;
}
public long Id { get; set; }
public EntityState State { get; set; }
public DateTime DateCreated { get; set; }
}
Klasa User:
public class User : EntityObject
{
public User()
{ }
public User(string applicationUserId, string email)
{
SetUserData(applicationUserId, email);
}
public virtual UserData UserData { get; set; }
public virtual UserDetails UserDetails { get; set; }
public virtual UserAddressInfo UserAddressInfo { get; set; }
}
Klasa UserDetails:
public class UserDetails : EntityObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public virtual User User { get; set; }
}
Pozostałe klasy (UserAddressInfo, UserData) są dokładnie tak samo skonstruowane jak UserDetails więc ich nie pokazuje:
A to jest Fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions
.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<UserData>()
.HasKey(e => e.Id);
modelBuilder.Entity<UserData>()
.HasRequired(ad => ad.User)
.WithOptional(s => s.UserData);
modelBuilder.Entity<UserAddressInfo>()
.HasKey(e => e.Id);
modelBuilder.Entity<UserAddressInfo>()
.HasRequired(ad => ad.User)
.WithOptional(s => s.UserAddressInfo);
modelBuilder.Entity<UserDetails>()
.HasKey(e => e.Id);
modelBuilder.Entity<UserDetails>()
.HasRequired(ad => ad.User)
.WithOptional(s => s.UserDetails);
}
Wszystko pięknie się stworzyło i teraz User się loguje i ma konieczność uzupełnienia danych (UserDetails i UserAddressInfo).
Kiedy zapisuję UserDetails to metoda SaveChange() przechodzi (ForeignKey User_Id został użyty jakby pierwszy raz?).
Natomiast kiedy chce zapisać UserAddressInfo to SaveChange wypieprza błąd:
Violation of PRIMARY KEY constraint 'PK_dbo.UserAddressInfo'. Cannot insert duplicate key in object 'dbo.UserAddressInfo'. The duplicate key value is (1).
The statement has been terminated.
Kiedy zamienię kolejność czyli najpierw zapisze UserAddressInfo a potem UserDetails to błąd wyskakuje dla UserDetails.
Co jest nie tak zrobione?
W SQL tabele stworzyły się tak, że:
UserDetails:
Columns:
Id(PK, FK, bigint, not null),
cała reszta...
Keys:
PK_dbo.UserDetails
FK_dbo.UserDetails_dbo.User_Id
W UserAddressInfo jest dokładnie tylko zamiast UserDetails -> UserAddressInfo itd.
Dlaczego to się wypieprza? A najlepsze, że wyjątek leci, a w bazie rekord jest zapisany!