Я хочу работать с существующей, общей базой данных (я не могу изменить дизайн базы данных) с Linq-to-SQL и.NET 4.5 на С#. База данных находится на SQL Server 2008.
Чтобы прояснить мою проблему, я создал минимальный рабочий пример:
Рассмотрим следующий (бессмысленный) пример, где две таблицы представляют людей и компании. Каждый человек работает ровно в одной компании (без работы здесь), и каждая компания возглавляется ровно одним человеком:
Я хочу использовать 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
Дополнительная информация: в наборе изменений был обнаружен цикл
Сначала я мог бы попытаться вставить компанию, но это приведет к еще одному исключению, которое жалуется на нарушение нарушенного внешнего ключа (отсутствует лидер).
Есть ли способ обойти эту проблему, не касаясь дизайна базы данных или переноса создания строк в хранимую процедуру?
Вы даже не можете решить эту проблему с помощью raw SQL. У вас есть взаимная зависимость от внешнего ключа. Вы создали две таблицы, в которые вы никогда не сможете вставлять строки.
Вы можете создать одну фиктивную строку в каждой таблице, а внешний ключ отключен. Затем вы можете сначала вставить обе строки, указывающие на фиктивные строки. Затем вы обновляете их, чтобы установить в реальных значениях теперь, когда известны взаимные идентификаторы.
Я рекомендую сделать один из столбцов внешнего ключа нулевым, чтобы вы могли вставлять две строки один за другим. Но вы сказали, что не хотите изменять схему.
Учитывая нормальные формы в дизайне базы данных, описанный выше сценарий должен быть разбит и необходимо создать 3 таблицы. 2 таблицы (Person and Company), имеющие собственные первичные ключи, которые не зависят друг от друга и третья таблица (PersonCompanyRelation), которая будет иметь зависимые внешние ключи как для Лица, так и для Компании, которые будут определять отношения.
[EDIT]: ссылка для поддержки вышеуказанного аргумента, http://msdn.microsoft.com/en-us/library/vstudio/bb386950(v=vs.90).aspx
обычно вам нужно вставить только одну сущность. Но я боюсь, что вам понадобится соотношение 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();
}