VS 2005, Framework 2.0
Работаю над двузвенной СУБД
Общее решение выглядит примерно так:
Client клиентская компонента (WindowsApplication, формы, сериализуемые объекты которыми оперирует приложение)
DAL — data access logic серверная компонента (WindowsService, имеет доступ к БД, возвращает клиенту полученные из БД сериализуемые объекты)
MS SQL (собственно БД)
Сериализуемый объект (СО) это набор скалярных полей и таблиц
class serObj
{
int ID;
string name;
...
DataTable Moves;
...
}
DAL реадизует интерфейс через который к нему обращается клиент
class DAL:MarshalByRef, IDAL
{
void Read(ref serObj)
{serObj.Moves = sql.ReadMove(....); serObj.Moves.Constraints.Add(new UniqueConstraint(...)); ...}
}
На таблицы содержащиеся в СО, наложены ограничения. Так как клиент "тонкий", то вся логика работы с СО заложена в DAL, в том числе и ограничения.
Если в БД все хорошо, то клиент получает готовую, заполненную таблицу с ограничениями и работает с ней не нарушая логики организации данных.
Плохо становится когда в БД, содержаться записи не удовлетворяющие этим ограничениям (в моем случае при переносе из другой БД).
В моем случае ситуация развивалась так:
DAL получает таблицу с ошибочными сведениями и пытается прикрутить к ней constraint (например UniqueConstraint), возникает исключение, если его обработать и все таки вернуть таблицу клиенту, то исключение тут же возникает в клиенте, при этом исключение не содержит никакой полезной информации об ограничении.
Повозился с Contsraint и DataTable, и понял что при такой схеме либо придется возвращать данные без ограничения (т.е их вряд ли исправят), либо возвращать неполные\пустые, но с ограничением.
Подумал и переделал DAL следующим образом добавил событие которое отправляется в догонку данным и служит сигналом о том что данные не удовлетворяют наложенным сервером ограничениям и их необходимо исправить.
class DAL:MarshalByRef, IDAL
{
event NeedConstraintHandler NeedConstraint;
void Read(ref serObj)
{
serObj.Moves = sql.ReadMove(....);
try { serObj.Moves.Constraints.Add(new UniqueConstraint(...)); }
catch (Exception exc) {NeedConstraint(NeedConstraintEventArgs args); }
...
}
Когда переделал понял, что событие происходит раньше чем возвращаются сами данные.
Т.е СО еще в обработке, а клиент уже получил сигнал о том, что он (СО) неверен.
Эту ситуацию конечно можно разрешить, генерирую событие из отдельного потока и синхронировав этот поток с потоком обрабатывающим СО.
Оглядел все свое "творчество" и понял, что решение сложное и интуитивно мне кажется неоправданно сложное. Мне кажется, что где-то я прокололся и все должно решаться проще. А вот как понять не могу.
Собственно вопрос: Как организовать обмен DataTable с ограничениями между двумя удаленными компонентами, таким образом чтобы они могли обмениваться данными которые не удовлетворяют этим ограничениям?
PS Есть конечно вариант создать для каждого поля-таблицы вспомогательное поле содеражащее исходные данные для ограничения
(само ограничение по-моему не сериализуемо) и собирать и прикручивать на клиенте. НО во первых это требует жесткого контроля за кодом, т.е после каждого обращения к DAL, необходимо проверить не надо ли чего прикрутить к полученным таблицам. Второе НО субъективное на мой взгляд этот вариант не очень клиентский, не очень "тонкий клиент" получается.