Как получить PK при заполнении данных с использованием структуры сущностей, используя несколько условий

Использование Entity-Framework-6 в сочетании с MVC-5 и Identity-framework-2. Я хотел найти первичный ключ из первого семени и вставить найденный ключ во второе семя. Я использую несколько условий для поиска ключа, но почему-то мое лямбда-выражение не работает или написано неправильно.

Что мне не хватает?

Глядя здесь: /migrations/configurations.cs

Я использую этот пример https://stackoverflow.com/a/24936095/2910930 в качестве основы для остальной части моего семени .

protected override void Seed(ApplicationDbContext context)
{
    bool itWorks = WriteReferenceData(context);
    base.Seed(context);
}

private bool WriteReferenceData(ApplicationDbContext ctx)
{
    DbContextTransaction transaction = null;
    bool succeeded = false;
    try
    {
        transaction = ctx.Database.BeginTransaction();

        CreateDetails(ctx);
        CreateRooms(ctx);

        ctx.SaveChanges();
        transaction.Commit();
        succeeded = true;
     }
     catch (Exception ex)
     {
         if (transaction != null) { transaction.Rollback(); transaction.Dispose(); }
         succeeded = false;
     }
     return succeeded;
}

В первое семя я вставлю несколько записей, ПК будет сгенерирован в БД. Когда я запускаю этот метод, записи вставляются правильно и генерируется ПК.

// FIRST SEED
private void CreateDetails(ApplicationDbContext ctx)
{
  var Details = new List<Detail>
  {
      new Detail { MaxUsers = 1, RoomName = "WorkRoom"},
      new Detail { MaxUsers = 2, RoomName = "WorkRoom"},
      new Detail { MaxUsers = 3, RoomName = "PlayRoom"}
  };
  Details.ForEach(s => ctx.Detail.AddOrUpdate(p => p.DetailID, s));
  ctx.SaveChanges();
}

// SECOND SEED
private void CreateRooms(ApplicationDbContext ctx)
{
    // THIS IS NOT WORKING CORRECTLY
    Int16 ID = ctx.Detail
                  .Single(x => 
                      x.RoomName == "WorkRoom" &&   
                      x.MaxUsers == 2).DetailID;

    var Rooms = new List<Room>
    {
        // 1 person
        new Room { RoomID = "X-16", DetailID = ID}
        new Room { RoomID = "X-17", DetailID = ID}
    };
    Rooms.ForEach(s => ctx.Room.AddOrUpdate(p => p.RoomID, s));
    ctx.SaveChanges();
}

person Bunkerbuster    schedule 12.08.2014    source источник
comment
EF исправит для вас значения внешнего ключа, если вы добавите дочерние элементы в свойство навигации (набор дочерних элементов) родителя.   -  person Keith Payne    schedule 12.08.2014
comment
Какая связь между Room и Detail? Почему есть свойство DetailID в Room и RoomName в Detail?   -  person Keith Payne    schedule 12.08.2014
comment
@keith: Комната и детали имеют отношение многие к одному. У меня много комнат и в них 1 деталь. Как вы можете видеть, это DetailKey FK в таблице Rooms. И EF не будет автоматически исправлять внешний ключ, потому что они связаны определенными условиями.   -  person Bunkerbuster    schedule 12.08.2014
comment
Я вижу, RoomName предназначен не для Room, а для Detail.   -  person Keith Payne    schedule 12.08.2014
comment
ctx.Detail.AddOrUpdate(p => p.DetailID, s) выглядит подозрительно. В примерах они используют естественные ключи для поиска строк, которые могут быть обновлены, а не суррогатный ключ. Можете ли вы подтвердить, что после первого SaveChanges() в таблице есть три строки?   -  person Keith Payne    schedule 12.08.2014
comment
@keith: Да, имя комнаты — это столбец в таблице сведений. И да, я вставил 3 столбца в 3 строки. Дизайн таблицы работает (это не проблема). Но что-то не так в моем лямбда-выражении (чтение DetailID) (и отладка - это разочаровывающая работа, когда вы используете метод Seed).   -  person Bunkerbuster    schedule 13.08.2014
comment
PS лучшим названием для названия комнаты было бы тип комнаты :)   -  person Bunkerbuster    schedule 13.08.2014


Ответы (1)


После того, как я много прочитал о linq и Lambda, ответ оказался намного проще, чем я думал.

var detail = ctx.Detail.Where(x => x.DetailRoomName == "Patientroom" && x.MaxUsers == 1);

int detailID = detail.Single().DetailID;

var Rooms = new List<Room>
{
    // 1 person
    new Room { RoomID = "X-16", DetailID = detailID }
    new Room { RoomID = "X-17", DetailID = detailID }
};
person Bunkerbuster    schedule 12.09.2014