Еще одно усложнение «многие ко многим» - Entity Framework 4.1 DbContext - PullRequest
1 голос
/ 13 октября 2011

Я использую первый метод DB, EF 4.1 с кодом POCO DbContext gen.

Моя база данных имеет отношение "многие ко многим", как показано ниже:

Сотрудник

EmployeeId

EmployeeName

Account

AccountId

AccountName

EmployeeAccount

EmployeeId

AccountId

Проблема возникает, когда я пытаюсь обновить сотрудника и изменить назначение его учетной записи на ранее существующую учетную запись, поэтому яв основном я делаю это, как показано ниже:

using(context)
{
  var query = from e in context.Employees.Include(f => f.Accounts)
              where e.EmployeeId == employeeId
              select;

  Employee emp = query.FirstOrDefault()
}

emp.EmployeeName = "Test";

emp.Accounts.Clear();

Account act = MethodThatLooksUpAccountByName("SomeAccountName");

emp.Accounts.Add(act);

using(context)
{
  context.Accounts.Attach(act);

  emp.State = EntityState.Modified;

  context.Employees.Attach(emp);

  context.SaveChanges();
}

Сгенерированный SQL выполняет обновление таблицы [Employee], вообще ничего для [EmployeeAccount], без удаления, без вставки.

1 Ответ

1 голос
/ 13 октября 2011

Попробуйте удалить (хотя бы) последние Attach. Вам также не нужно устанавливать состояние на Modified, потому что вы находитесь в прикрепленном сценарии (emp загружено из БД) и отслеживание изменений распознает, что изменилось:

var query = from e in context.Employees.Include(f => f.Accounts)
            where e.EmployeeId == employeeId
            select;
Employee emp = query.FirstOrDefault()

emp.EmployeeName = "Test";
emp.Accounts.Clear();

Account act = MethodThatLooksUpAccountByName("SomeAccountName");
// next line is only necessary if MethodThatLooksUpAccountByName
// uses another context. If it uses the same context you can remove this line.
context.Accounts.Attach(act); 

emp.Accounts.Add(act);

context.SaveChanges();

Это должно работать на мой взгляд.

Изменить после того, как вы изменили код в вопросе:

Второй контекст выполняет свое собственное отслеживание изменений. Поэтому он не распознает, что вы удалили учетные записи и добавили новую. Он должен работать следующим образом:

using(...context...)
{
    var query = from e in context.Employees.Include(f => f.Accounts)
                where e.EmployeeId == employeeId
                select;

    Employee emp = query.FirstOrDefault()
}

Account act = MethodThatLooksUpAccountByName("SomeAccountName");

using(...context...)
{
    context.Employees.Attach(emp);
    context.Accounts.Attach(act);

    emp.EmployeeName = "Test";
    emp.Accounts.Clear();
    emp.Accounts.Add(act);

    context.SaveChanges();
}

У меня есть чувство, это не то, что вы хотите. Делали ли вы изменения сотрудника (очистка старых учетных записей и добавление новых учетных записей) в состоянии, отделенном от последнего контекста? Проблема с коллекцией «многие ко многим» состоит в том, что вы должны загрузить или присоединить старую коллекцию Account в контексте, где вы хотите очистить или изменить ее. Нет никакого способа вызвать какие-либо операторы DELETE или INSERT в таблице ссылок, установив любое скалярное свойство или установив состояние для любого объекта. Только обнаружение изменений в коллекциях приведет к обновлению таблицы ссылок EF.

...