|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Добрый день, У меня задача переписать/доработать существующее приложение, написанное на Access + Excel. Новое приложение: Серверная часть – SQL Server 2008R2(уже почти закончена), Клиентская часть – C#, Winforms, .Net не выше 4.0 (в процессе разработки). Я сейчас продумываю организацию работы с данными клиентского приложения. Буду рад услышать комментарии, советы. В этом приложении Entity Framework использоваться не будет, соответственно работать нужно будет или через нетипизированные или через типизированные Dataset-ы. Первым стал вопрос использовать типизированный Dataset или нет. Сеппа в своей книге, подробно описав каждый из них, предлагает выбор делать каждому, но сам он склоняется к обычным, нетипизированным Dataset-ам. Его аргументы: быстрее(если обращаться к полям не по имени и не по индексу, а как к объекту), нет глюков(он описывает какие именно), бОльшая свобода. Как ни странно я остановился именно на типизированном. Почему так. Во-первых, пришлось задуматься о конфликтах обновления. В Access при обновлении записи в форме, в случае конфликта записи, выдается сообщение, что пока вы правили запись, другой пользователь внес в нее свои изменения. Пользователю предлагается выбор: скопировать запись в буфер и оценить различия, отказаться от своих изменений или сохранить свою версию записи. Мастер создания типизированного Dataset берет на себя организацию проверки на конфликты. Если не ошибаюсь CommadBuilder делает тоже самое, генерируя логику обновления, а именно условие отбора строится таким образом, когда исходное значение каждого поля обновляемой записи сравнивается со значением соотв.поля в базе данных на сервере. Есть поле timestamp или нет его, а такой подход всегда предотвратит конфликт записей. В общем, без системы решения конфликтов остаться я не хочу, свою систему с псевдо блокированием записей делать тоже не хочу, поэтому решил, что предлагаемый механизм меня устроит. Но тут оказалось, что буквально первый же источник данных, который я предложил тестовому гриду, причем также созданный с помощью мастера, оказался не в состоянии создать команды на удаление/обновление/добавление. CommandBuilder также не смог их создать. Там запрос по нескольким таблицам, очевидно, не по возможностям мастера и CommandBuilder. Писать аналогичные запросы руками, чтобы потом подсовывать их соответствующим командам, не то, что утомительно, это просто было бы невыносимо. Обошелся так. Мастер создает типизированный Dataset, и простую логику обновления/удаления/добавления по таблице, а я вручную добавляю в таблицу дополнительные нужные поля, используемые запросом на выборку, и задаю тот самый «сложный» запрос на выборку по нескольким таблицам. В общем, в таком режиме проектировать не утомительно. Во-вторых. Типизированный Dataset позволяет мне расширять код , созданный мастером, используя partial классы. В Access при вводе данных интерфейс каждой формы (события формы/контролов), должен обеспечивать различные проверки. Недостаток в том, что код может дублироваться от формы к форме. Мне показалось, что в C# программе я смогу вынести все подобные проверки в partial классы соответствующих типизированных DataTable, написать их один раз. Эдакие триггеры. Тем самым сняв нагрузку с интерфейса. Я так думал… Но чем больше занимаюсь темой, тем больше разочарование. Надеюсь, я просто еще не представляю, как это можно реализовать лучшим образом и мне подскажут. Что хотелось бы. Все проверки вынести в partial классы типизированных Dataset. Проверки разместить на события объекта DataTable. Событий вроде как достаточно: https://msdn.microsoft.com/en-us/library/system.data.datatable_events(v=vs.110).aspx Но, что получается. Допустим перед сохранением записи на событие RowChanging выполнены проверки, выданы сообщения и нужно отменить сохранение и продолжить редактирование. Отменить событие можно только возбудив исключение. Но при этом все внесенные изменения будут потеряны, запись вернется в исходное состояние. Вольно или невольно, но я тяготею к привычному мне способу работы, а именно, когда запись в гриде изменена и производится попытка перехода на другую запись, вызывая сохранение записи, в нашем случае это событие RowChanging. Так вот, если проверка не прошла и событие нужно отменить, то пользователь, получив сообщения должен остаться на той же записи грида, а сама запись должна остаться в том же самом состоянии, в которое ее привел пользователь. Но в моем случае, когда пользователь переходит на другую запись грида, вызывая тем самым событие DataTable RowChanging, отмена события(возбуждение исключения) приводит к том, что запись возвращается в исходное состояние, в котором была до редактирования, а текущей станет та запись, на которую собственно был осуществлен переход. А вот если бы я повесил все проверки на события грида, то очевидно, я бы добился желаемого мной способа взаимодействия. Но именно этого(ориентированность на события интерфейса) мне и хотелось бы избежать. В общем я в замешательстве. Как быть? Не получится обойтись только событиями Dataset? Кстати, а ведь если вести работу не через интерфейс, а программно, то в этом случае я ж ведь никак не смогу воспрепятствовать событию RowChanging. Если возбужу исключение, то потеряю все внесенные данные. Мысль о том, что изменения можно запомнить, а потом снова внести в туже строку, гоню от себя подальше . Так можно утонуть в этой событийной зависимости. Можно, конечно, запретить делать правки в гридах, а все изменения вносить только через «карточки», где взять контроль над событиями в свои руки, но делать так мне не хочется. Хотелось бы услышать советы, комментарии, мнения. Спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 17:46 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль Сергей, Ну вот только для контроля версий записей использовать УГ под названием ADO.NET Dataset? Все легко и чисто решается с помощью EF и timestamps. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 17:55 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Axeleron, > Все легко и чисто решается с помощью EF и timestamps timestamps может быть на таблице, а может и нет. Это может не от меня зависеть. Поэтому хотелось иметь универсальность. >EF Это Entity Framework? в этом приложение его не будет. >Ну вот только для контроля версий записей использовать УГ под названием ADO.NET Dataset? Сорри, УГ, это что? Вообще-то вопрос не понял. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 18:23 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль СергейСорри, УГ, это что? УГ - унылое говно. Вы же на .NET форум пришли - привыкайте. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 18:25 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль Сергейtimestamps может быть на таблице, а может и нет. Это может не от меня зависеть. Поэтому хотелось иметь универсальность. Иметь TimeStamps а таблице - это в принципе хорошая парктика. Отвыкайте от идеологии Access, переходя на .NET (да и не только). Это и даст Вам универсальность. Добавить лишнее поле в таблицу никогда не поздно и выполняется всего одной SQL-командой. Вакшуль Сергейв этом приложение его не будет. Можно через ХПы, но на DataSet'ах нынче уже моветон что-то писать, если, конечно, не поддержка легаси-систем. Вакшуль СергейВообще-то вопрос не понял. Вы пытаетесь репродуцировать поведение Access в .NET (я знаю о чем говорю, так как начинал с Access), но ряди этого использовать устаревшие методы непрактично и бесперспективно, когда полно других технологий для достижения ваших целей. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 18:47 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
AxeleronИметь TimeStamps а таблице - это в принципе хорошая парктика. Отвыкайте от идеологии Access, переходя на .NET (да и не только). Это и даст Вам универсальность. Добавить лишнее поле в таблицу никогда не поздно и выполняется всего одной SQL-командой. а причем тут привычки? Как я уже говорил: timestamps может быть на таблице, а может и нет. Это может не от меня зависеть. Поэтому хотелось иметь универсальность. Ну не все зависит от меня. Такого поля может и не быть. А если говорить по факту - они есть не везде. Да, и вообще выбор у меня только между типизированным и нетипизированным Dataset, а о concurrency я упомянул только в разрезе того чтобы было понятно, почему склоняюсь к типизированным Dataset. Axeleronесли, конечно, не поддержка легаси-систем. да, это именно расширение существующей системы. AxeleronВы пытаетесь репродуцировать поведение Access в .NET (я знаю о чем говорю, так как начинал с Access), но ряди этого использовать устаревшие методы непрактично и бесперспективно, когда полно других технологий для достижения ваших целей. Проводя аналогии с Access, я говорил о том, что хотел бы организовать так, чтобы запись нельзя было покинуть, пока поля не будут нужным образом заполнены. Это вы об этом "непрактично и бесперспективно"? ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 19:38 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
кто нибудь, напишите вкратце, что хотел автор? :) ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 19:41 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль Сергейа причем тут привычки? Как я уже говорил: timestamps может быть на таблице, а может и нет. Это может не от меня зависеть. Поэтому хотелось иметь универсальность. Ну не все зависит от меня. Такого поля может и не быть. А если говорить по факту - они есть не везде. Да, и вообще выбор у меня только между типизированным и нетипизированным Dataset, а о concurrency я упомянул только в разрезе того чтобы было понятно, почему склоняюсь к типизированным Dataset. Тут я Вам ничем помочь не могу. Раз выбор у Вас только между типизированным и нетипизированным Dataset'ом... Вакшуль СергейПроводя аналогии с Access, я говорил о том, что хотел бы организовать так, чтобы запись нельзя было покинуть, пока поля не будут нужным образом заполнены. Это вы об этом "непрактично и бесперспективно"? Нет, боюсь, мы с Вами не на одной и той же волне... Roman Mejtesкто нибудь, напишите вкратце, что хотел автор? :) Много чего одновременно и в то же самое время неясно. Бось, там кашу в голове будет не просто расхлебать... :( ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 19:53 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль Сергей, Автор, Вы можете по пунктам вкратце и структурированно изложить ваши вопросы? ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 19:54 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
AxeleronМного чего одновременно и в то же самое время неясно. Бось, там кашу в голове будет не просто расхлебать... :( излагал в расчете, что по ходу рассуждений меня поправят/направят. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 20:05 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль СергейAxeleronМного чего одновременно и в то же самое время неясно. Бось, там кашу в голове будет не просто расхлебать... :( излагал в расчете, что по ходу рассуждений меня поправят/направят. Боюсь народ недопонял. Просто вышел обширный список хотелок с жесткими ограничениями по имплементации. Такого не бывает. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 20:15 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль Сергей, все нормально, работай дальше, все получится ну, а "переход на следующую запись на гриде" все же надо отловить на гриде допустим RowChanging выдает - "не покидай меня" и грид не покидает запись ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 20:18 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
ViPRos, ViPRosвсе нормально, работай дальше, все получится :) ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 20:24 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль Сергей, у каждого нормального грида есть механизм валидации записи ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 20:27 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
ViPRos, Да, можно ловить событиями грида. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2015, 20:31 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль Сергей, предположим Вы запись редактируете не в гриде, а в карточке. Как Вы в таком случае реализуете валидацию? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 01:52 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
skyANA, по кнопке ОК-Отмена :) ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 01:59 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
ViPRosskyANA, по кнопке ОК-Отмена :)то есть по событию компонента UI, а не DataSet. ЧТД :) ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 02:08 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
skyANA, а какое ж событие Датасет отвечает за валидацию записи? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 02:18 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
ViPRosskyANA, а какое ж событие Датасет отвечает за валидацию записи?Выше RowChanging обсуждается. А вообще формулировка "событие отвечает за валидацию записи" не корректна. Событие только инициирует валидацию. Желательно, чтобы последняя была написана так, чтобы можно было использовать и с гридом, и в карточке, и без UI, как выше упоминает ТС. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 02:37 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
skyANAВакшуль Сергей, предположим Вы запись редактируете не в гриде, а в карточке. Как Вы в таком случае реализуете валидацию? Я сейчас в поиске решения, которое меня удовлетворит. А какая разница, в гриде или карточке. И там и там призяка к данным. То же самое событие RowChanging. Если бы событие DataTable RowChanging можно было цивилизовано отменить, то я бы удовлетворился этим событием. Т.е. при первом взгляде на вещи мне показалось, что достаточно все проверки повесить на события RowChanging и ColumnChanging и если событие RowChanging не пришлось отменять(все проверки прошли нормально), то произойдет событие RowChanged, по которому можно было бы данные передать на сервер. Но, похоже (если я ошибаюсь, то поправьте), что предполагается, что на событиях RowChanging и ColumnChanging выловленные ошибки нужно помещать в св-во Row.RowError, и не передавать на сервер, пока эти ошибки не будут исправлены. Так, нет? Поправьте. skyANAто есть по событию компонента UI, а не DataSet. ЧТД :) а я то как раз купился на обилие событий объекта DataTable. Подумал, что интерфейс можно облегчить, сняв с него проверки и возложить их на события DataTable. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 03:28 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
skyANA, skyANAЖелательно, чтобы последняя была написана так, чтобы можно было использовать и с гридом, и в карточке, и без UI, как выше упоминает ТС. skyANAи без UI Если задействовать возможности UI, то я могу представить, как проверить валидность записи перед сохранением и не дать сохранить невалидные данные. А вот как быть в случае "без UI", ведь если положится на событие DataTable RowChanging, то ведь его корректно отменить нельзя. Как я говорил, если возбудить исключение, то все внесенные в записи данные будут потеряны. Хотя этот вопрос сейчас второстепенный и наверно притянут мной за уши. Просто в идеале я бы именно так и хотел: "Желательно, чтобы последняя была написана так, чтобы можно было использовать и с гридом, и в карточке, и без UI" вообще у меня складывается впечатление, что мои собеседники событие DataTable RowChanging не используют вообще. Так, нет? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 03:44 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль СергейПодумал, что интерфейс можно облегчить, сняв с него проверки и возложить их на события DataTable.Интерфейс можно облегчить, если не пихать в него кучу логики, которой там не место :) Вынесите проверки в отдельный(е) класс(ы)-валидатор(ы). ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 10:07 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль Сергейвообще у меня складывается впечатление, что мои собеседники событие DataTable RowChanging не используют вообще. Так, нет?Не то чтобы вообще, но оочень редко. Плотно использовались DataTable-ы в моей работе 9 с лишним лет назад. Но тогда я писал кастомные контролы для редактирования в гриде, что тупо не позволяют вводить всякую фигню. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 10:23 |
|
Принцип организации работы с данными
|
|||
---|---|---|---|
#18+
Вакшуль Сергей, может опишите конкретные кейсы, что Вам надо реализовать? У DataRow есть метод RejectChanges . То есть Вы можете отменить изменения для конкретной строки не кидая исключений. Также есть методы DataGrid.CancelEdit и DataGridView.CancelEdit . ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2015, 10:30 |
|
|
start [/forum/topic.php?fid=20&msg=38914296&tid=1401763]: |
0ms |
get settings: |
8ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
30ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
58ms |
get tp. blocked users: |
1ms |
others: | 14ms |
total: | 145ms |
0 / 0 |