У меня есть интересная загадка, и я надеюсь, что другие смогут помочь пролить немного света.
При вставке новой записи с использованием EF6 в таблицу, в которой составной ключ состоит из двух направляющих, где один член должен быть назначен из БД, а другой имеет свое значение, предоставленное приложением, я получаю смешанную информацию ответы.
Для одной таблицы вставка происходит без каких-либо проблем, в то время как для другой с точно такой же настройкой ключа и идентификатора столбца происходит сбой вставки с сообщением «InvalidOperationException: зависимое свойство в ReferentialConstraint сопоставляется сгенерированным хранилищем столбцом , Колонка: «ID». Ниже приведены (упрощенные) классы с их настройками конфигурации
Класс, который не может быть вставлен:
public class User
{
public Guid ID { get; set; }
public Guid CompanyId { get; set; }
public Guid OrganisationId { get; set; }
public String PasswordHash { get; set; }
public String Salt { get; set; }
public String UserName { get; set; }
public virtual Company Company { get; set; }
public virtual Organisation Organisation { get; set; }
// <inconsequential members omitted>
}
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
HasKey(u => new { u.CompanyId, u.ID });
Property(u => u.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(u => u.UserName).IsRequired().HasMaxLength(256);
Property(u => u.PasswordHash).IsRequired().HasMaxLength(256);
Property(u => u.Salt).IsRequired().HasMaxLength(256);
HasRequired(c => c.Company).WithMany(c => c.Users).HasForeignKey(c => c.CompanyId).WillCascadeOnDelete(false);
HasRequired(c => c.Organization).WithMany(c => c.Users).HasForeignKey(p => p.OrganizationID).WillCascadeOnDelete(false);
// < inconsequential members omitted>
}
}
Класс, который вставляет без проблем:
public class AdditionalInformation
{
public Guid ID { get; set; }
public Guid CompanyId { get; set; }
public Guid CustomFieldId { get; set; }
public Guid UserId{ get; set; }
public virtual Company Company { get; set; }
public virtual User User { get; set; }
// <inconsequential members omitted>
}
public class AdditionalInformationConfiguration : EntityTypeConfiguration<AdditionalInformation>
{
public AdditionalInformationConfiguration()
{
HasKey(ai => new { ai.CompanyId, ai.ID });
Property(u => u.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasOptional(ai => ai.User).WithMany(u => u.UserAdditionalInformations).HasForeignKey(ai => new { ai.CompanyId, ai.UserID });
// <inconsequential members omitted>
}
}
Простой тест, который я использую:
using (var context = new DataContext())
{
var user = context.Users.First(f => f.Company.Subdomain.StartsWith("demo"));
var customField = context.CustomFields.First(f => f.CompanyId == user.CompanyId);
context.Users.Add(new User() { CompanyId = user.CompanyId, PasswordHash = "hash", Salt = "salt", UserName = "anew@entry.com" });
context.AdditionalInformations.Add(new UserAdditionalInformation() { CustomFieldID = customField.ID, CompanyId = user.CompanyId, UserID = user.ID });
context.SaveChanges();
}
Как видите, оба класса имеют члена ID, а также члена CompanyId. У них обоих есть ключ, определенный как {CompanyId, Id} и DatabaseGeneratedOption.Identity на элементе ID.
Я очень озадачен тем, почему, когда экземпляр класса AdditionalInformation
сохраняется в БД через DbContext, запись создается без проблем, в то время как класс User
генерирует исключение InvalidOperationException: зависимое свойство в ReferentialConstraint отображается в столбец, созданный хранилищем. Колонка: «ID». ошибка.