Обработка циклических зависимостей в Linq to SQL при вставке строк

1

Я хочу работать с существующей, общей базой данных (я не могу изменить дизайн базы данных) с Linq-to-SQL и.NET 4.5 на С#. База данных находится на SQL Server 2008.

Чтобы прояснить мою проблему, я создал минимальный рабочий пример:

Рассмотрим следующий (бессмысленный) пример, где две таблицы представляют людей и компании. Каждый человек работает ровно в одной компании (без работы здесь), и каждая компания возглавляется ровно одним человеком:

Изображение 174551

Я хочу использовать Linq-to-SQL для создания новой компании и нового человека, который ее ведет.

Я бы закодировал что-то вроде этого:

using (var ctx = new DataContext()) {
    var company = new daCompany() { name = "company1" };
    var person = new daPerson() { name = "person1" };
    company.daPerson = person;
    person.daCompany = company;
    ctx.daCompanies.InsertOnSubmit(company);
    ctx.daPersons.InsertOnSubmit(person);
    ctx.SubmitChanges();
}

но SubmitChanges() выдает исключение:

Необработанное исключение типа "System.InvalidOperationException" произошло в System.Data.Linq.dll

Дополнительная информация: в наборе изменений был обнаружен цикл

Сначала я мог бы попытаться вставить компанию, но это приведет к еще одному исключению, которое жалуется на нарушение нарушенного внешнего ключа (отсутствует лидер).

Есть ли способ обойти эту проблему, не касаясь дизайна базы данных или переноса создания строк в хранимую процедуру?

  • 1
    Одна сторона отношений должна поддерживать 0-1 отношения, чтобы это работало. Либо человек может быть оторван от компании, либо компания может быть без лидера ... по крайней мере, на некоторое время. Без этого даже хранимая процедура не будет работать для вас.
Теги:
linq
linq-to-sql

3 ответа

2
Лучший ответ

Вы даже не можете решить эту проблему с помощью raw SQL. У вас есть взаимная зависимость от внешнего ключа. Вы создали две таблицы, в которые вы никогда не сможете вставлять строки.

Вы можете создать одну фиктивную строку в каждой таблице, а внешний ключ отключен. Затем вы можете сначала вставить обе строки, указывающие на фиктивные строки. Затем вы обновляете их, чтобы установить в реальных значениях теперь, когда известны взаимные идентификаторы.

Я рекомендую сделать один из столбцов внешнего ключа нулевым, чтобы вы могли вставлять две строки один за другим. Но вы сказали, что не хотите изменять схему.

  • 0
    К сожалению, схема базы данных не создана мной, я просто должен работать с ней. В настоящее время все создания обрабатываются с помощью хранимых процедур (которые могут отключить проверку ограничений FK), но это кажется мне слишком громоздким
  • 0
    Можете ли вы выполнить DDL? Вы можете отключить FKs самостоятельно. В SQL Server нет способа вставки в две таблицы одновременно.
0

Учитывая нормальные формы в дизайне базы данных, описанный выше сценарий должен быть разбит и необходимо создать 3 таблицы. 2 таблицы (Person and Company), имеющие собственные первичные ключи, которые не зависят друг от друга и третья таблица (PersonCompanyRelation), которая будет иметь зависимые внешние ключи как для Лица, так и для Компании, которые будут определять отношения.

[EDIT]: ссылка для поддержки вышеуказанного аргумента, http://msdn.microsoft.com/en-us/library/vstudio/bb386950(v=vs.90).aspx

0

обычно вам нужно вставить только одну сущность. Но я боюсь, что вам понадобится соотношение 1..0-1.

Вы пробовали этот код?

using (var ctx = new DataContext()) 
{
var company = new daCompany() { name = "company1" };
var person = new daPerson() { name = "person1" };
company.daPerson = person;
person.daCompany = company;
ctx.daCompanies.InsertOnSubmit(company);
//ctx.daPersons.InsertOnSubmit(person);
ctx.SubmitChanges();
}
  • 0
    да, я пробовал это, к сожалению, это не будет работать (то же исключение)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню