Пишу первое приложение на C#. Появилась загвоздка при удалении записи из БД.
Структура БД — таблица Machines (машины) и таблица Services (обслуживания).
Machines:
ID — уникальный ключ
Name — название
Services
ID — уникальный ключ
Date — дата
Description — описание
IDMachine — код машины
Таблицы связаны — Machines.ID -> Services.IDMachine (один ко многим). Хочу, чтобы при удалении записи из Machines автоматом удалялись и дочерние записи в Services. Уже перепробовал разные варианты, однако добиться каскадного удаления не получается.
Ниже код реализации:
....
// подготовка данных
eLibraDataSet.Relations.Add("Machines_Services", eLibraDataSet.Machines.IDColumn,
eLibraDataSet.Services.IDMachineColumn,false);
fkc = new ForeignKeyConstraint("Machines_ServicesFK",
eLibraDataSet.Machines.IDColumn, eLibraDataSet.Services.IDMachineColumn);
fkc.DeleteRule = Rule.Cascade;
fkc.UpdateRule = Rule.SetNull;
eLibraDataSet.Machines.Constraints.Add(fkc);
eLibraDataSet.EnforceConstraints = false; //это ограничение включаю непосредственно перед удалением, поэтому пока отключаю его
machinesTableAdapter.Fill(eLibraDataSet.Machines);
servicesTableAdapter.Fill(eLibraDataSet.Services);
....
// непоcредственно удаление
eLibraDataSet.EnforceConstraints = true;
machinesTableAdapter.Delete(0); //удаляю первую запись в главной таблице, для нее есть записи в подчиненной
eLibraDataSet.EnforceConstraints = false;
machinesTableAdapter.Update(eLibraDataSet.Machines); // но после обновления в подчиненной записи остаются на месте
servicesTableAdapter.Update(eLibraDataSet.Services);
machinesTableAdapter.Fill(eLibraDataSet.Machines);
servicesTableAdapter.Fill(eLibraDataSet.Services);
...
Не выходит у меня таким образом каскадно удалять записи. Из главной таблицы удаляется запись, а подчиненные записи остаются.
Может кто-нибудь подскажет, каким образом надо организовать это удаление?
Здравствуйте, frik, Вы писали:
F>Здравствуйте, Nike85, Вы писали:
F>а почему бы не реализовать это удаление на уровне базы данных?
Хотелось бы сделать это в программе, средством шарпа. Если честно, не знаю, поддерживает ли MS Access (использую эту БД) триггеры, чтобы реализовать каскадное удаление в самой программе. Кажется, нет.
Но даже если поддерживает, хотелось иметь возможность включать/отключать контроль за удалением записей. Можно, конечно, устроить дебаты, как лучше в данном случае поступить — реализовывать данную возможность на уровне БД или приложения. С радостью выслушаю дводы за и против. Однак сейчас мне важнее разобраться почему этот код не работает и как его заставить работать
Здравствуйте, Nike85, Вы писали:
N>Здравствуйте, frik, Вы писали:
F>>Здравствуйте, Nike85, Вы писали:
F>>а почему бы не реализовать это удаление на уровне базы данных?
N>Хотелось бы сделать это в программе, средством шарпа. Если честно, не знаю, поддерживает ли MS Access (использую эту БД) триггеры, чтобы реализовать каскадное удаление в самой программе. Кажется, нет. N>Но даже если поддерживает, хотелось иметь возможность включать/отключать контроль за удалением записей. Можно, конечно, устроить дебаты, как лучше в данном случае поступить — реализовывать данную возможность на уровне БД или приложения. С радостью выслушаю дводы за и против. Однак сейчас мне важнее разобраться почему этот код не работает и как его заставить работать
конечно поддерживает. думаю любая БД такое поддерживает, это типа целостоность БД, если нет родительской записи то и не должно быть зависящих от нее записей
Здравствуйте, frik, Вы писали:
N>>Хотелось бы сделать это в программе, средством шарпа. Если честно, не знаю, поддерживает ли MS Access (использую эту БД) триггеры, чтобы реализовать каскадное удаление в самой программе. Кажется, нет.
F>конечно поддерживает. думаю любая БД такое поддерживает, это типа целостоность БД, если нет родительской записи то и не должно быть зависящих от нее записей
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, frik, Вы писали:
N>>>Хотелось бы сделать это в программе, средством шарпа. Если честно, не знаю, поддерживает ли MS Access (использую эту БД) триггеры, чтобы реализовать каскадное удаление в самой программе. Кажется, нет.
F>>конечно поддерживает. думаю любая БД такое поддерживает, это типа целостоность БД, если нет родительской записи то и не должно быть зависящих от нее записей
L>триггеры?
ээ так каскадное удаление это не триггеры, я про каскадное удаление писал
Здравствуйте, frik, Вы писали:
F>Здравствуйте, Nike85, Вы писали:
F>а почему бы не реализовать это удаление на уровне базы данных?
И все же, как реализовать это с помощью C#? Зачем тогда в режиме дизайнера Dataset'а в Visual Studio можно добавлять связи между таблицами, устанавливать внешние ключи, указывая для них правила, срабатывющие в том числе и на удаление записей?
Здравствуйте, Nike85, Вы писали:
N>Здравствуйте, frik, Вы писали:
F>>Здравствуйте, Nike85, Вы писали:
F>>а почему бы не реализовать это удаление на уровне базы данных?
N>И все же, как реализовать это с помощью C#? Зачем тогда в режиме дизайнера Dataset'а в Visual Studio можно добавлять связи между таблицами, устанавливать внешние ключи, указывая для них правила, срабатывющие в том числе и на удаление записей?
Dataset нужен для создания полного снимка БД, соответственно он должен повторить структуру бд
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Nike85, Вы писали:
N>>Здравствуйте, frik, Вы писали:
F>>>Здравствуйте, Nike85, Вы писали:
F>>>а почему бы не реализовать это удаление на уровне базы данных?
N>>И все же, как реализовать это с помощью C#? Зачем тогда в режиме дизайнера Dataset'а в Visual Studio можно добавлять связи между таблицами, устанавливать внешние ключи, указывая для них правила, срабатывющие в том числе и на удаление записей?
А>Dataset нужен для создания полного снимка БД, соответственно он должен повторить структуру бд
Да, в самой БД я не прописал связи и правила при удалении записей. Но почему, если в я создаю динамически во время выполнения Relation между таблицами, то программа ругается на отсутствие связанных записей в главной таблице (т.е. механизм связей работает), а при удалении записи в главной таблице не срабатывает каскадное удаление в дочерней?
N>Да, в самой БД я не прописал связи и правила при удалении записей. Но почему, если в я создаю динамически во время выполнения Relation между таблицами, то программа ругается на отсутствие связанных записей в главной таблице (т.е. механизм связей работает), а при удалении записи в главной таблице не срабатывает каскадное удаление в дочерней?
по поводу ругания могу сказать -читай документацию. а вобще зачем этот лишний геморой- не проще ли все зависимости прописать в БД, и пусть бд сама следит. это ее работа
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Nike85, Вы писали:
N>>Да, в самой БД я не прописал связи и правила при удалении записей. Но почему, если в я создаю динамически во время выполнения Relation между таблицами, то программа ругается на отсутствие связанных записей в главной таблице (т.е. механизм связей работает), а при удалении записи в главной таблице не срабатывает каскадное удаление в дочерней?
А>по поводу ругания могу сказать -читай документацию. а вобще зачем этот лишний геморой- не проще ли все зависимости прописать в БД, и пусть бд сама следит. это ее работа
Ругание то очевидно, из-за чего происходит, т.к. не выполняются связи (к примеру, при открытой дочерней таблице и закрытой родительской). Не понятно, почему шарп также основательно не выполняет свои обязательства fkc.DeleteRule = Rule.Cascade.
Попробую в самой аксессовской БД прописать ограничения, может это меня и устроит. НО все равно, почему шарп не делает этого сам???
Здравствуйте, Nike85, Вы писали:
N>Не выходит у меня таким образом каскадно удалять записи. Из главной таблицы удаляется запись, а подчиненные записи остаются. N>Может кто-нибудь подскажет, каким образом надо организовать это удаление?
Советую почитать книгу ADO.NET Девида Сеппа. Там очень толково все описано. Конкретно твой случай — глава "Сложные случаи обновления данных". Редакция книги не важна — там мало изменений, ИМХО.
Если нужно будет — напишу пример кода... Когда делал курсовой, у меня нормально удалялись записи (по примерам книги).
Здравствуйте, Nike85, Вы писали:
N> Хочу, чтобы при удалении записи из Machines автоматом удалялись и дочерние записи в Services.
А ты случаем не перепутал таблицу, к которой ты FK добавляешь? Это во-первых. А во-вторых у FK нужно еще инициализировать свойство AcceptRejectRules. По умолчанию оно равно None.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, Nike85, Вы писали:
N>Таблицы связаны — Machines.ID -> Services.IDMachine (один ко многим). Хочу, чтобы при удалении записи из Machines автоматом удалялись и дочерние записи в Services. Уже перепробовал разные варианты, однако добиться каскадного удаления не получается.
Давайте опишу, как всё должно работать. Можете воспользоваться отладкой и найти, где идёт не так.
0. Имеются две таблицы, между ними связь 1-ко-многим, во второй таблице внешний ключ. Настройки внешнего ключа: DeleteRule=Cascade, AcceptRejectRule=None.
1. Constraint'ы включены. Удаляем запись в главной таблице — запись переходит в состояние Deleted, связанные записи в дочерней таблице так же переходят в состояние Deleted — в соответствии с правилом DeleteRule=Cascade
2. Выключаем constraint'ы. Обновляем записи из главной таблицы — запись удаляется из БД, в DataTable ей делается Commit и она удаляется из таблицы. Дочерние записи не затрагиваются (они так и остаются в состоянии Deleted) благодаря тому, что AcceptRejectRule=None
3. Обновляем записи дочерней таблицы — Deleted записи удаляются из БД и из DataTable.
Попробуйте поотлаживать простейшие случаи, обратите внимание на состояние (свойство RowState) записей.