Лучший отвечающий
Обновление данных в связанных таблицах ADO.NET Entity Framework

Вопрос
-
Подскажите пожалуйста. Есть 2 таблицы со связью один ко многим. Используется MS SQL и ADO.NET Entity Framework. Возникает проблема при каскадном обновлении связанных полей между таблицами. При этом удаление строк происходит нормально. При изменении первичного ключа возникает ошибка о том, что первичный ключ изменять нельзя. Почему ? И где находятся настройки, изменяющий этот параметр ? При изменении внешнего ключа ошибка возникает при вызове метода SaveChanges() объекта типа ObjectContext. Каким образом нужно правильно обновлять связанные данные втаблицах? Спасибо.
14 февраля 2011 г. 20:55
Ответы
-
Давайте рассмотрим реакцию SQL Server на каскадное обновление ключей.
use tempdb go create table t1(t1_id int primary key, t1_value int) go create table t2(t2_id int identity primary key, t1_id int) go create table t3(t3_id int identity primary key, t2_id int) go alter table [dbo].[t2] with check add constraint [FK_t2_t1] foreign key([t1_id]) references [t1] ([t1_id]) on update cascade on delete cascade go alter table [dbo].[t3] with check add constraint [FK_t3_t2] foreign key([t2_id]) references [t2] ([t2_id]) on update cascade on delete cascade go insert into t1 values(1, 1) go insert into t2 values((select top 1 t1_id from t1 where t1_value = 1)) go insert into t3 values((select top 1 t2_id from t2 where t1_id = (select top 1 t1_id from t1 where t1_value = 1))) go -- Вы можете обновить первичный ключ, т.к. -- значение в колонку t1_id было вставлено явно. update t1 set t1_id = 12345 where t1_id = (select top 1 t1_id from t1 where t1_value = 1) go -- Вы не можете выполнить следующий update, -- т.к. поле t2_id определено как identity и не может быть актуализировано. -- Для вставки удаленных значений из колонки со свойством identity -- используйте параметр set identity_insert on update t2 set t2_id = 12345 where t1_id = (select top 1 t1_id from t1 where t1_value = 1) go select * from t1 select * from t2 select * from t3 go alter table t2 drop constraint FK_t2_t1 go alter table t3 drop constraint FK_t3_t2 go drop table t1, t2, t3 go
- Помечено в качестве ответа Abolmasov Dmitry 17 февраля 2011 г. 6:06
15 февраля 2011 г. 22:07 -
Подскажите пожалуйста. Есть 2 таблицы со связью один ко многим. Используется MS SQL и ADO.NET Entity Framework. Возникает проблема при каскадном обновлении связанных полей между таблицами. При этом удаление строк происходит нормально. При изменении первичного ключа возникает ошибка о том, что первичный ключ изменять нельзя. Почему ? И где находятся настройки, изменяющий этот параметр ? При изменении внешнего ключа ошибка возникает при вызове метода SaveChanges() объекта типа ObjectContext. Каким образом нужно правильно обновлять связанные данные втаблицах? Спасибо.
1) "При изменении первичного ключа возникает ошибка о том, что первичный ключ изменять нельзя." - на сколько мне известно это действительно так и относится к этому нужно как одной из особенностей EF. Кстати использовал MS SQL и ADO.NET Entity Framework в паре крупных коммерческих проектах (500-600 таблиц) и ни разу не возникала такая потребность!
2) "При изменении внешнего ключа ошибка возникает при вызове метода SaveChanges() объекта типа ObjectContext." - внешний ключ менять не нужно! Пример того как нужно использовать EF для изменения внешнего ключа:
using (Model1Container mc = new Model1Container()) { // Создание записей ParentEntity pe1 = new ParentEntity() { Value = "ParentEntity1" }; mc.ParentEntity.AddObject(pe1); // Добавление нового объекта ParentEntity ParentEntity pe2 = new ParentEntity() { Value = "ParentEntity1" }; mc.ParentEntity.AddObject(pe2); // Добавление нового объекта ParentEntity ChildEntity ch1 = new ChildEntity() { Value = "ChildEntity1" }; pe1.ChildEntity.Add(ch1); // Проставляем связь ChildEntity с ParentEntity mc.ChildEntity.AddObject(ch1); // Добавление нового объекта ChildEntity ChildEntity ch2 = new ChildEntity() { Value = "ChildEntity2" }; pe2.ChildEntity.Add(ch2); // Проставляем связь ChildEntity с ParentEntity mc.ChildEntity.AddObject(ch2); // Добавление нового объекта ChildEntity mc.SaveChanges(); // Сохраняем данные // Меняем связи pe1.ChildEntity.Remove(ch1); pe2.ChildEntity.Remove(ch2); pe1.ChildEntity.Add(ch2); pe2.ChildEntity.Add(ch1); mc.SaveChanges(); // Сохраняем данные };
- Предложено в качестве ответа DenisX555 20 февраля 2011 г. 13:22
- Помечено в качестве ответа Abolmasov Dmitry 21 февраля 2011 г. 11:58
19 февраля 2011 г. 19:55
Все ответы
-
Давайте рассмотрим реакцию SQL Server на каскадное обновление ключей.
use tempdb go create table t1(t1_id int primary key, t1_value int) go create table t2(t2_id int identity primary key, t1_id int) go create table t3(t3_id int identity primary key, t2_id int) go alter table [dbo].[t2] with check add constraint [FK_t2_t1] foreign key([t1_id]) references [t1] ([t1_id]) on update cascade on delete cascade go alter table [dbo].[t3] with check add constraint [FK_t3_t2] foreign key([t2_id]) references [t2] ([t2_id]) on update cascade on delete cascade go insert into t1 values(1, 1) go insert into t2 values((select top 1 t1_id from t1 where t1_value = 1)) go insert into t3 values((select top 1 t2_id from t2 where t1_id = (select top 1 t1_id from t1 where t1_value = 1))) go -- Вы можете обновить первичный ключ, т.к. -- значение в колонку t1_id было вставлено явно. update t1 set t1_id = 12345 where t1_id = (select top 1 t1_id from t1 where t1_value = 1) go -- Вы не можете выполнить следующий update, -- т.к. поле t2_id определено как identity и не может быть актуализировано. -- Для вставки удаленных значений из колонки со свойством identity -- используйте параметр set identity_insert on update t2 set t2_id = 12345 where t1_id = (select top 1 t1_id from t1 where t1_value = 1) go select * from t1 select * from t2 select * from t3 go alter table t2 drop constraint FK_t2_t1 go alter table t3 drop constraint FK_t3_t2 go drop table t1, t2, t3 go
- Помечено в качестве ответа Abolmasov Dmitry 17 февраля 2011 г. 6:06
15 февраля 2011 г. 22:07 -
Подскажите пожалуйста. Есть 2 таблицы со связью один ко многим. Используется MS SQL и ADO.NET Entity Framework. Возникает проблема при каскадном обновлении связанных полей между таблицами. При этом удаление строк происходит нормально. При изменении первичного ключа возникает ошибка о том, что первичный ключ изменять нельзя. Почему ? И где находятся настройки, изменяющий этот параметр ? При изменении внешнего ключа ошибка возникает при вызове метода SaveChanges() объекта типа ObjectContext. Каким образом нужно правильно обновлять связанные данные втаблицах? Спасибо.
1) "При изменении первичного ключа возникает ошибка о том, что первичный ключ изменять нельзя." - на сколько мне известно это действительно так и относится к этому нужно как одной из особенностей EF. Кстати использовал MS SQL и ADO.NET Entity Framework в паре крупных коммерческих проектах (500-600 таблиц) и ни разу не возникала такая потребность!
2) "При изменении внешнего ключа ошибка возникает при вызове метода SaveChanges() объекта типа ObjectContext." - внешний ключ менять не нужно! Пример того как нужно использовать EF для изменения внешнего ключа:
using (Model1Container mc = new Model1Container()) { // Создание записей ParentEntity pe1 = new ParentEntity() { Value = "ParentEntity1" }; mc.ParentEntity.AddObject(pe1); // Добавление нового объекта ParentEntity ParentEntity pe2 = new ParentEntity() { Value = "ParentEntity1" }; mc.ParentEntity.AddObject(pe2); // Добавление нового объекта ParentEntity ChildEntity ch1 = new ChildEntity() { Value = "ChildEntity1" }; pe1.ChildEntity.Add(ch1); // Проставляем связь ChildEntity с ParentEntity mc.ChildEntity.AddObject(ch1); // Добавление нового объекта ChildEntity ChildEntity ch2 = new ChildEntity() { Value = "ChildEntity2" }; pe2.ChildEntity.Add(ch2); // Проставляем связь ChildEntity с ParentEntity mc.ChildEntity.AddObject(ch2); // Добавление нового объекта ChildEntity mc.SaveChanges(); // Сохраняем данные // Меняем связи pe1.ChildEntity.Remove(ch1); pe2.ChildEntity.Remove(ch2); pe1.ChildEntity.Add(ch2); pe2.ChildEntity.Add(ch1); mc.SaveChanges(); // Сохраняем данные };
- Предложено в качестве ответа DenisX555 20 февраля 2011 г. 13:22
- Помечено в качестве ответа Abolmasov Dmitry 21 февраля 2011 г. 11:58
19 февраля 2011 г. 19:55 -
Спасибо. Можно ещё один вопрос. Можно ли из кода EntityFramework или мастеров Visual Studio установить ограничение unique для отдельного поля таблицы? Или в случае с ADO.NET EntityFramework это ограничение должно быть физически установлено в самой базе MS SQL ?20 февраля 2011 г. 11:03
-
Спасибо. Можно ещё один вопрос. Можно ли из кода EntityFramework или мастеров Visual Studio установить ограничение unique для отдельного поля таблицы? Или в случае с ADO.NET EntityFramework это ограничение должно быть физически установлено в самой базе MS SQL ?
Делать это конечно же нужно "в самой базе MS SQL".20 февраля 2011 г. 13:20