Мне сложно описать это словами, поэтому я буду использовать некоторый код, чтобы объяснить себя и свою проблему.
Так что представьте, у меня есть два класса ClassA
и ClassB
:
class ClassA
{
public int ClassAId { get; set; }
public string Name { get; set; }
}
[Owned]
class ClassAOwned
{
public int ClassAId { get; set; }
public string Name { get; set; }
}
class ClassB
{
public int ClassBId { get; set; }
public string Action { get; set; }
public ClassAOwned ClassA { get; set; }
}
, как вы можете видеть ClassB
содержит ClassA
, но у меня есть другой класс для него ClassAOwned
, потому что я хочу, чтобы ClassB
владел ClassA
(сведет его столбцы в таблицу ClassB
), но также имеет ClassA
DbSet как отдельная таблица (и, насколько я понимаю, класс сущностей не может принадлежать и иметь собственный DbSet одновременно), поэтому мне пришлось использовать 2 разных класса. Вот мой контекст, чтобы было легче понять:
class TestContext : DbContext
{
public DbSet<ClassA> ClassAs { get; set; }
public DbSet<ClassB> ClassBs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseInMemoryDatabase("TestContext");
}
}
Теперь моя проблема возникает, когда я пытаюсь одновременно вставить ClassA
и ClassB
в контекст, и мне нужно сопоставить их значения ClassAId
, которые генерирует поставщик базы данных:
var testContext = new TestContext();
var classA = new ClassA
{
Name = "classAName"
};
var classB = new ClassB
{
Action = "create",
ClassA = new ClassAOwned
{
ClassAId = classA.ClassAId,
Name = classA.Name
}
};
testContext.ClassAs.Add(classA);
testContext.ClassBs.Add(classB);
classB.ClassA.ClassAId = classA.ClassAId;
testContext.SaveChanges();
при использовании InMemoryDatabase
следующий вызов:
testContext.ClassAs.Add(classA);
фактически меняет classA.ClassAId
на правильное сгенерированное значение, однако при использовании SQL-сервера classA.ClassAId
устанавливается на int.MinValue
, поэтому следующий вызов:
classB.ClassA.ClassAId = classA.ClassAId;
устанавливает classB.ClassA.ClassAId
в int.MinValue
. и последний звонок:
testContext.SaveChanges();
меняет classA.ClassAId
на правильное сгенерированное значение, но classB.ClassA.ClassAId
остается равным int.MinValue
, и это значение вставляется в базу данных.
Мой вопрос: есть ли способ сообщить ядру EF, что при добавлении двух сущностей в контекст задайте свойству любое значение, сгенерированное для первичного ключа другой сущности? Таким образом, функциональность, которую я ищу, точно такая же, как добавление двух сущностей, у которых есть внешний ключ, за исключением того, что в данном случае это не действительно внешний ключ.
Простой обходной путь - установить «внешний ключ» (classB.ClassA.ClassAId
) после testContext.SaveChanges()
и снова сохранить изменения, но затем он становится двумя отдельными операциями, и что если вторая не удастся? База данных будет в недопустимом состоянии.