Здравствуйте, baranovda, Вы писали:
B>На выборку данных эти оба великолепно спариваются. B>Из IQueryable получаем IDbCommand, из IDbCommand — IDbDataReader, а последним заполняем DataTable.
Речь не о чтении данных. Речь об идеологии. В датасетах хорошо — отсоедененность и автономная работа, плохо — нетипизированнойсть и запутанность АПИ.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Как сделано у нас — не могу. Как делается самостоятельно (сорри что невнятно — по памяти. давно решалось):
1) Вы можете использовать в качестве кодогенератора что угодно — тот же reegenerator (http://www.reegenerator.com/Features.htm). T4 мне больше нравится
2) Читаем вводную статью, например — http://www.olegsych.com/2007/12/text-template-transformation-toolkit/. В ней куча самплов. Для DataSet'a нет. Если не находится (мне проще было написать своё — специфика):
3) Общая идея T4 — если нам надо что-то сложнее чем подстановка имени класса — генерим строку и скармливаем через this.WriteLine. Всё что нам надо — превратить xsd датасета в текст. Что использовать — XSLT, собственный быдлокод+XmlReader или CodeDom — на ваше усмотрение.
Не, давайте уж разбираться
G>Смотрю сгенерированные EF классы — оповещения будут.
Это оповещения на изменение свойств элемента. Они хороши для биндинга к конкретной сущности. Попробуйте отследить добавление/удаление/изменение любой сущности — причём именно те, что будут отражены в базе. У ObjectContext только одно событие — SavingChanges. Вы конеш можете проводить валидацию внутри сущностей, но это во-первых намекает о жирной модели. Во-вторых, вы не сможете так проверять сложные ограничения, что требуют доступа ко всему контексту. Или хотя бы отследить тот факт, что сущность поменяла родителя
Кстати, попробуйте реализовать ограничение на уникальность любого поля. EDM позволяет определить только один Key. Даже элементарное требование несуществования двух сущностей с одинаковыми именами уже требует приседаний. Напомню — нарушение ограничений должно обнаруживаться при попытке изменения сущности, чтобы можно было его отловить и исправить на месте. Вы внимательней присмотритесь к EDM. Как средство описания модели данных она довольно убога.
G>Для работы с графами объектов в UI я бы тоже рекомендовал viewmodel создавать.
1) мы всё ещё обсуждаем десктоп клиента? основное предназначение DAL здесь — данные для биндинга к UI + чуть-чуть логики. Фактически, процентов так 90 требуемого функционала придётся писать ручками.
2) Под ViewModel вы понимаете кучу классов-обёрток, что изображают из себя сущности/коллекции, а на практике работают с контекстом? Если да — то мы говорим ровно об одном и том же — в чистом виде EF непригоден для использования для биндинга. Кстати, реализовывать интерфейсы, нужные для биндинга — такой гемморой...
G>Ну если рассматривать только десктоп-клиент с непосредственным доступом в базу, то вооще зачем нужен disconnected режим? G>Если многозвенное приложение, то рецепт я привел выше.
Даже если у нас многозвенное _intranet_ приложение, то лучше использовать tcp endpoints ч/з WCF. REST для локальной сети — оверкилл в квадрате. Disconnected режим нужен для одной простой вещи — масштабируемости. Вы имели счастье наблюдать, как один полумёртвый celeron 1.8/512ram не задыхаясь держит нагрузку, необходимую для _одновременного_ обслуживания 200 пользователей? При Disconnected режиме эти 200 одновременных соединений вполне себе превращаются в пару тысяч клиентов — это с учётом боттлнеков по утрам, т.к. обращения к базе нужны, когда надо сохранить/обновить данные/выполнить нетривиальные операции типа полнотекстового поиска. Обычно работа с сервером не затягивается дольше чем на пару секунд. В среднем пользователь обращается за повторными сведениями раз в 10 минут (это средняя температура по больнице, сами понимаете). Эффективность сами посчитаете?
Естественно, для time-critical-data прямые обращения к серверу удобнее. Но это совсем отдельная тема.
G>Многие решения по работе с данными отдают костылями.
Ага. но датасеты _на десктоп-клиенте_ какие-то менее костылятые.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, gandjustas.
S>Не, давайте уж разбираться
G>>Смотрю сгенерированные EF классы — оповещения будут. S>Это оповещения на изменение свойств элемента. Они хороши для биндинга к конкретной сущности. Попробуйте отследить добавление/удаление/изменение любой сущности — причём именно те, что будут отражены в базе. У ObjectContext только одно событие — SavingChanges. Вы конеш можете проводить валидацию внутри сущностей, но это во-первых намекает о жирной модели. Во-вторых, вы не сможете так проверять сложные ограничения, что требуют доступа ко всему контексту. Или хотя бы отследить тот факт, что сущность поменяла родителя
Это все требует вытягивания большого количества данных в память. По соображениям производительности такого лучше не делать, при небольшой нагрузке на приложение база начнет загибаться.
S>Кстати, попробуйте реализовать ограничение на уникальность любого поля. EDM позволяет определить только один Key. Даже элементарное требование несуществования двух сущностей с одинаковыми именами уже требует приседаний. Напомню — нарушение ограничений должно обнаруживаться при попытке изменения сущности, чтобы можно было его отловить и исправить на месте.
!context.Table.Any(e => e.Name == "xxx")
???
Сомневаюсь что датасеты сделают это лучше.
S>Вы внимательней присмотритесь к EDM. Как средство описания модели данных она довольно убога.
Многие недостатки исправят во второй версии EF, остается только ждать.
G>>Ну если рассматривать только десктоп-клиент с непосредственным доступом в базу, то вооще зачем нужен disconnected режим? G>>Если многозвенное приложение, то рецепт я привел выше.
S>Даже если у нас многозвенное _intranet_ приложение, то лучше использовать tcp endpoints ч/з WCF. REST для локальной сети — оверкилл в квадрате.
С чего бы? Как раз в локльной сети оверхеда и незаметно будет.
Учитывая возможности кеширования HTTP можно сделать так, чтобы суммарный трафик оказался меньше.
S>Disconnected режим нужен для одной простой вещи — масштабируемости. Вы имели счастье наблюдать, как один полумёртвый celeron 1.8/512ram не задыхаясь держит нагрузку, необходимую для _одновременного_ обслуживания 200 пользователей? При Disconnected режиме эти 200 одновременных соединений вполне себе превращаются в пару тысяч клиентов — это с учётом боттлнеков по утрам, т.к. обращения к базе нужны, когда надо сохранить/обновить данные/выполнить нетривиальные операции типа полнотекстового поиска. Обычно работа с сервером не затягивается дольше чем на пару секунд. В среднем пользователь обращается за повторными сведениями раз в 10 минут (это средняя температура по больнице, сами понимаете). Эффективность сами посчитаете?
Открытый контекст EF не заставляет держать открытое соединение.
G>>Многие решения по работе с данными отдают костылями. S>Ага. но датасеты _на десктоп-клиенте_ какие-то менее костылятые.
Мне кажется что вы просто не умеете готовить EF.
Здравствуйте, gandjustas.
G>Это все требует вытягивания большого количества данных в память. По соображениям производительности такого лучше не делать, при небольшой нагрузке на приложение база начнет загибаться.
0) почему база-то будет загибаться??? ей практически всё равно сколько данных отдавать, если они хорошо нормализованы и хороший index coverage. Скорее наоборот, куча мелких обращений обойдётся дороже.
1) у нас всё ещё десктоп клиент, так? В память выгребаются только данные, нужные клиенту. От пары тысяч сущностей он загнётся?
2) Ограничения пишутся не от балды — они отражают существенные связи в предметной области. Как правило, ограничения, что проверяются на клиенте значимы для проведения конкретных бизнес-операций. Естественно ограничения на клиенте не служат для _защиты_ от несогласованных данных — это обязанность субд. Они нужны для _раннего обнаружения_ ошибок. В разницу будем углубляться?
3) Объём данных, необходимых для проведения конкретной бизнес-операции обычно небольшой — допустим, у нас не может быть одинаковых категорий продуктов. Список категорий обычно достаточно небольшой и его удаётся кэшировать на клиенте. В случае, когда это недопустимо — либо дёргаем базу, либо забиваем на препроверки и сосредотачиваемся на интерактивном мерже при обнаружении конфликтов.
G>
G>!context.Table.Any(e => e.Name == "xxx")
G>
G>???
1) Вы проверяете наличие элемента с таким именем в базе, не в контексте. Если вы удалили сущность в контексте — ограничение покажет лодную информацию.
2) Вы обязаны вызывать эту проверку _во всех_ методах, обращающихся к e.Name/добавляющих новый объект в контекст. В том числе и внутри биндинга — вам уже нужны сторонние обёртки.
3) У вас идёт обращение к серверу на каждое изменение имени. Если у вас массовые обновления/вставки — сервер загнётся.
4) даже если вы выгрузите сущности в список, вам придётся синхронизировать измсенения в контексте и в списке — чтобы не было противоречий.
G>Сомневаюсь что датасеты сделают это лучше.
Вызывается _один_ раз в конструкторе. Генерится дизайнером. Используются индексы на rbtree.
S>>Вы внимательней присмотритесь к EDM. Как средство описания модели данных она довольно убога. G>Многие недостатки исправят во второй версии EF, остается только ждать.
Ну, фундаментально нового ничего не обещано. Из интересного — интеллектуальный маппинг, computed columns, edm-defined functions. Но да, с интересом ждём.
S>>Даже если у нас многозвенное _intranet_ приложение, то лучше использовать tcp endpoints ч/з WCF. REST для локальной сети — оверкилл в квадрате. G>С чего бы? Как раз в локльной сети оверхеда и незаметно будет. G>Учитывая возможности кеширования HTTP можно сделать так, чтобы суммарный трафик оказался меньше.
У нас допустим дедлок именно в пропускной способности сети был.
Кэширование не спасёт. В локальной сети пользователи — не обезьянки, что выгребают горы одинакового трафа. Они гребут данные, что нужны им для работы, и данные пересекаются безумно редко. посему — сорри
G>Открытый контекст EF не заставляет держать открытое соединение.
Мы ведь обсуждали выгоды disconnected mode вроде? Как-то вы с темы на тему перескакиваете. Тем не менее:
1) если у вас регулярные проверки типа той что написана выше — требует.
2) если у вас свой локальный кэш — всё ок. Другое дело, что с ef локальный кэш приходится писать ручками.
G>Мне кажется что вы просто не умеете готовить EF.
Дык поделитесь рецептами
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, gandjustas.
G>>Это все требует вытягивания большого количества данных в память. По соображениям производительности такого лучше не делать, при небольшой нагрузке на приложение база начнет загибаться.
S>0) почему база-то будет загибаться??? ей практически всё равно сколько данных отдавать, если они хорошо нормализованы и хороший index coverage. Скорее наоборот, куча мелких обращений обойдётся дороже. S>1) у нас всё ещё десктоп клиент, так? В память выгребаются только данные, нужные клиенту. От пары тысяч сущностей он загнётся?
Ну вариант один клиент — одна база и рассматривать по большому счету не стоит. В таких случаях можно держать SqlCE базу и работать с resultset_ами, напрямую смотрящими в таблицу.
Если у вас несколько клиентов смотрят в одну базу, то вам все равно придется проверять актуальность локальных копий и частенько гонять change-setы туда-сюда.
S>2) Ограничения пишутся не от балды — они отражают существенные связи в предметной области. Как правило, ограничения, что проверяются на клиенте значимы для проведения конкретных бизнес-операций. Естественно ограничения на клиенте не служат для _защиты_ от несогласованных данных — это обязанность субд. Они нужны для _раннего обнаружения_ ошибок. В разницу будем углубляться?
Я в курсе какие ограничения зачем пишутся. Но это не отметает необходимости загружать много данных из базу для проверки некоторых из них.
S>3) Объём данных, необходимых для проведения конкретной бизнес-операции обычно небольшой — допустим, у нас не может быть одинаковых категорий продуктов. Список категорий обычно достаточно небольшой и его удаётся кэшировать на клиенте. В случае, когда это недопустимо — либо дёргаем базу, либо забиваем на препроверки и сосредотачиваемся на интерактивном мерже при обнаружении конфликтов.
Ну это если один клиент на одну базу.
G>>
G>>!context.Table.Any(e => e.Name == "xxx")
G>>
G>>???
S>1) Вы проверяете наличие элемента с таким именем в базе, не в контексте. Если вы удалили сущность в контексте — ограничение покажет лодную информацию.
После каждого изменения данных их хорошо бы в базу писать, а то приложение упасть может свет вырубят и пр. Желательно чтобы по нажатию "сохранить" изменения дествительно сохранялись.
Проверка нужна непосредственно перед сохранением, чтобы красивый feedback обеспечить.
S>2) Вы обязаны вызывать эту проверку _во всех_ методах, обращающихся к e.Name/добавляющих новый объект в контекст. В том числе и внутри биндинга — вам уже нужны сторонние обёртки.
С чего это я обязан такое делать? Мне вполне хватит чтобы невалидные данные в базу не попали, для этого в принцие ничего кроме ограниченй в базе и не надо. Дополнительная проверка делается только для целей UI.
А уже в binding она нафиг не нужна.
S>3) У вас идёт обращение к серверу на каждое изменение имени. Если у вас массовые обновления/вставки — сервер загнётся.
Нет, обращения к серверу идут когда я вызываю SaveChanges, обычно это нажатие кнопки "Сохранить" или чего-то в этом роде.
S>4) даже если вы выгрузите сущности в список, вам придётся синхронизировать измсенения в контексте и в списке — чтобы не было противоречий.
Не нужно будет. Элементами списка будут являться теже сущности, что и в контексте.
G>>Сомневаюсь что датасеты сделают это лучше. S>
S>Вызывается _один_ раз в конструкторе. Генерится дизайнером. Используются индексы на rbtree.
Ну я в курсе, но как это гарантирует согласованность в БД при наличии нескольких клиентов?
S>>>Вы внимательней присмотритесь к EDM. Как средство описания модели данных она довольно убога. G>>Многие недостатки исправят во второй версии EF, остается только ждать. S>Ну, фундаментально нового ничего не обещано. Из интересного — интеллектуальный маппинг, computed columns, edm-defined functions. Но да, с интересом ждём.
S>>>Даже если у нас многозвенное _intranet_ приложение, то лучше использовать tcp endpoints ч/з WCF. REST для локальной сети — оверкилл в квадрате. G>>С чего бы? Как раз в локльной сети оверхеда и незаметно будет. G>>Учитывая возможности кеширования HTTP можно сделать так, чтобы суммарный трафик оказался меньше.
S>У нас допустим дедлок именно в пропускной способности сети был.
При передачи датасетов — я не сомневаюсь. Сам видел такое в одном проекте.
S>Кэширование не спасёт. В локальной сети пользователи — не обезьянки, что выгребают горы одинакового трафа. Они гребут данные, что нужны им для работы, и данные пересекаются безумно редко. посему — сорри
Клиентское кеширование, пользователь не будет много раз тянуть неизменяющиеся сущности. Суммарная нагрузка на сервер по траффику вполне может оказаться гораздо ниже, чем через WCF даже с бинарной сериализацией.
G>>Открытый контекст EF не заставляет держать открытое соединение. S>Мы ведь обсуждали выгоды disconnected mode вроде? Как-то вы с темы на тему перескакиваете. Тем не менее: S>1) если у вас регулярные проверки типа той что написана выше — требует.
Про сохранение данных я писал выше.
S>2) если у вас свой локальный кэш — всё ок. Другое дело, что с ef локальный кэш приходится писать ручками.
С чего вы взяли? сам по себе контекст EF обеспечивает локальный кеш.
G>>Мне кажется что вы просто не умеете готовить EF. S>Дык поделитесь рецептами
1)Для работы контекста совершенно необязательно держать открытым соединение. Нужно закрыть — context.Connection.Close();
2)Объекты из кеша контекста можно получить так:
from se in context.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged | EntityState.Modified | EntityState.Added)
where !se.IsRelationship
select se.Entity;
Допилить по вкусу.
3)Чтобы получить объекты без кеширования в контексте можно Linqовый запрос привести к типу ObjectQuyery<T> и вызывать Execute(MergeOption.NoTracking)
Здравствуйте, VladD2, Вы писали:
VD>Вань, а что же они у нас то не рулят на сервере?
Потому что их там нет, а те что есть — сам знаешь как писались...
VD>IT тут недавно рассказывал, что он какой-то там кусок на сервере переписал с использованием линка и скорость выросла в несколько раз.
Могу наспор переписать этот же кусок кода на хранимке, чтобы работал как минимум так же (другое дело, что думать придется) и могу придумать такой сценарий, что никакой линк не поможет... Ты это к чему собственно?
VD>Какое-то расхождение теории и практики.
Ты просто не внимательно читаешь. Речь не о хранимка vs линк, а о хранимка vs триггер. Я сам из нашей базы часть триггеров вычищал, лет несколько назад, когда она в очередной раз колом встала.
Про линки и запросы из кода — отдельный разговор.
Здравствуйте, VladD2, Вы писали:
VD> Нужно просто понимать одну простую вещь. MS SQL кэширует планы к запросам очень тупо.
Ты даже не представляешь, насколько умно он это делает.. =)
VD>Так вот генерируя динамически запросы от вас требуется делать так, чтобы они были одинаковыми.
Строго говоря, это не так. Все существенно сложнее и от этих мелочей довольно много зависит.
Откуда взялась идея, что у нас "один клиент-одна база"? Если из-за "В память выгребаются только данные, нужные клиенту" — мои извинения, конечно же имелась в виду память клиента.
G>Если у вас несколько клиентов смотрят в одну базу, то вам все равно придется проверять актуальность локальных копий и частенько гонять change-setы туда-сюда.
1) не совсем. изменяемые данные практически не пересекаются — это вопрос эффективномти организации работы пользователей. Как только у вас несколько пользователей начинает править одну и ту же информацию — смело топайте к заказчику и начинайте обсуждать эффективность организации трудового процесса
2) изменения вносимые пользователями как правило затрагивают кучу сущностей и не вносятся по частям из-за ограничений в субд. Точно так же их нельзя вытаскивать по частям. Поэтому чанжсеты гонять придётся всё равно. Точнее, в СУБД отправляются только изменённые данные, назад выгребаются данные целиком: из-за небольшого объёма данных получается быстрее и проще, чем кидать изменения с последней синхронизации и затем их мержить.
3) Регулярная синхронизация по таймеру неудобна пользователям. Проще дать им знакомую концепцию "открыть/сохранить", и предупреждать о потере информации/проводить обновление по требованию. Естественно, есть corner cases, когда нужно "данные сейчас", но это отдельная тема.
G>После каждого изменения данных их хорошо бы в базу писать, а то приложение упасть может свет вырубят и пр. Желательно чтобы по нажатию "сохранить" изменения дествительно сохранялись. G>Проверка нужна непосредственно перед сохранением, чтобы красивый feedback обеспечить.
Извините, я сейчас буду сильно ругаться и брызгать слюнями Вы программы для менеджеров пишете? Для красивых отчётов? Пользователям нафиг сдался красивый фидбак и программа. Они работают. Не с вашей программой, а делают свою работу. Программа — только инструмент — это она должна подстраиваться под пользователей. Если он допустил ошибку — программа должна помочь её исправить сразу же. Это всё равно что говорить что спеллчекер нужен для красивого фидбака при сохранении.
Потеря информации не решается программой с мгновенными сохранениями. Здесь нужен упсилятор и кошерный электрик. Мгновенные сохранения мешают пользователям — они вынуждены _постоянно_ контролировать свои действия, что повышает утомляемость. Естественный режим работы — правка-проверка-синхронизация. Это же азы дизайна UI, даже в университетах подобное в рамках курса ЧМВ (человеко-машинное взаимодействие) читается. Как вы пишете UI —
G>С чего это я обязан такое делать? Мне вполне хватит чтобы невалидные данные в базу не попали, для этого в принцие ничего кроме ограниченй в базе и не надо. Дополнительная проверка делается только для целей UI. G>А уже в binding она нафиг не нужна.
Выше уже сказано про мгновенные сохранения. У нас просто разный подход к написанию систем: для меня попытка записать некорректные данные в базу — ЧП + баг в клиенте. Если бы не было ограничения, данные в базе были бы повреждены, система неработоспособна. Всё.
G>Ну я в курсе, но как это гарантирует согласованность в БД при наличии нескольких клиентов?
Уже писалось. Ограничения на сервере и на клиенте выполняют разные роли. На сервере — последний спасательный круг, средство для отлова багов клиента. На клиенте — средство раннего отлова багов пользователя. Зачем надо — тоже писалось выше.
S>>У нас допустим дедлок именно в пропускной способности сети был. G>При передачи датасетов — я не сомневаюсь. Сам видел такое в одном проекте.
У нас не было передачи датасетов. У нас была передача tds от СУБД к клиентам процессор-память простаивали на треть, жёсткий почти на пределе, 100 мбит сеть — фсё (по таск манадждеру ~ 60-70%, по перфмону — дикая очередь пакетов).
G>Клиентское кеширование, пользователь не будет много раз тянуть неизменяющиеся сущности. Суммарная нагрузка на сервер по траффику вполне может оказаться гораздо ниже, чем через WCF даже с бинарной сериализацией.
Писал выше. Когда сущности нормализованы, отслеживание изменений/формирование чанжсета/мерж оказываются дороже простой заливки данных с нуля. Проверено неоднократно.
S>>2) если у вас свой локальный кэш — всё ок. Другое дело, что с ef локальный кэш приходится писать ручками. G>С чего вы взяли? сам по себе контекст EF обеспечивает локальный кеш. G>2)Объекты из кеша контекста можно получить так: G>
G>from se in context.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged | EntityState.Modified | EntityState.Added)
G>where !se.IsRelationship
G>select se.Entity;
G>
G>Допилить по вкусу.
На выходе имеем мешанину из сущностей различных типов, причём отслеживать изменения в контексте невозможно. Кэш нельзя использовать для удобной выборки локальных данных, для валидации при изменениях и для биндинга. Зачем он нужен в десктоп-клиенте?
У нас просто слишком разные подходы к написанию софта. Предлагаю закругляться. Спасибо за альтернативный взгляд
Здравствуйте, Sinix, Вы писали:
S>Потеря информации не решается программой с мгновенными сохранениями. Здесь нужен упсилятор и кошерный электрик. Мгновенные сохранения мешают пользователям — они вынуждены _постоянно_ контролировать свои действия, что повышает утомляемость. Естественный режим работы — правка-проверка-синхронизация. Это же азы дизайна UI, даже в университетах подобное в рамках курса ЧМВ (человеко-машинное взаимодействие) читается. Как вы пишете UI —
Естественный режим — это постоянное сохраенение + возможность отката до преидущих версий. Пользователи пищат от радости
Здравствуйте, Sinix, Вы писали:
C>>Естественный режим — это постоянное сохраенение + возможность отката до преидущих версий. Пользователи пищат от радости S>+1 S>Вы имеете в виду возможность отмены изменений, сделанных в текущем сеансе редактирования? Или отмену любого изменения за время существования системы?
В идеале — и то, и другое.
S>Первое вполне реализуемо — хотя бы фоновым бэкапом кэша. Второе — сами понимаете. S>Интересная тема конеш, но так мы скатимся к темпоральным базам и дизайну гуя для них. Есть ещё какие замечания?
Есть, но лень писать
В частности, все известные мне схемы общения с БД из десктопного клиента дохнут в тех или иных сценариях при работе через высоколатентные сети (Интернет).
Здравствуйте, Cyberax.
C>В частности, все известные мне схемы общения с БД из десктопного клиента дохнут в тех или иных сценариях при работе через высоколатентные сети (Интернет).
Дыкть ничего нового: пара клиентов — впн, филиалы — репликация по впн, anybody — сайт+вебсервисы (опционально впн )
Кстати вариант с partially disconected apps дохлые каналы переносит лучше всего.
Здравствуйте, Sinix, Вы писали:
C>>В частности, все известные мне схемы общения с БД из десктопного клиента дохнут в тех или иных сценариях при работе через высоколатентные сети (Интернет). S>Дыкть ничего нового: пара клиентов — впн, филиалы — репликация по впн, anybody — сайт+вебсервисы (опционально впн )
А чем VPN-то поможет? Он идти будет точно так же через медленные каналы.
Или имеешь в виду VPN + Remote Desktop? Так это неудобно, глючно и сложно. Репликация — это зачастую тоже не решение. Опять же, вопросы с когерентностью данных и контролем доступа начинаются.
S>Кстати вариант с partially disconected apps дохлые каналы переносит лучше всего.
А вот partially disconected-приложения как раз очень плохо дружат с классическими БД.
Здравствуйте, Cyberax C>А чем VPN-то поможет? Он идти будет точно так же через медленные каналы.
Не-не, в смысле что тут ещё изобрести-то можно. Ремот десктоп даже и не рассматривался — он только для файл-серверов хорош.
А из-за чего по вашему мнению бд дохнут и какие варианты не будут дохнуть? Просто интересно что же такого можно наизобретать. Единственная причина что я вижу — затянувшиеся сессии + блокировки. Как уже писалось, partially disconnected резко сокращает число обращений к субд.
C>А вот partially disconected-приложения как раз очень плохо дружат с классическими БД.
Может мы под partially disconected разные вещи понимаем? Я вслед за МС и Сеппой под partially disconected понимаю софтину, которая большую часть времени работает автономно и изредка обращается к СУБД за данными/сохраняет изменения.
Я не въезжаю, почему СУБД с ними дружить не будет.
Если вы про приложения с репликацией в локальную in-memory бд — то они зовутся offline clients вообще-то.
Про репликацию полностью согласен. Тем не менее, какие вы предлагаете варианты по первым двум сценариям (пара удалённых пользователей и филиалы)?
Здравствуйте, Sinix, Вы писали:
S>А из-за чего по вашему мнению бд дохнут и какие варианты не будут дохнуть? Просто интересно что же такого можно наизобретать. Единственная причина что я вижу — затянувшиеся сессии + блокировки. Как уже писалось, partially disconnected резко сокращает число обращений к субд.
Основная проблема — латентность и сравнительно низкая пропускная способность каналов. В локалке часто можно сделать запрос и показать результат без видимой задержки для пользователя. В WAN такое просто не прокатит.
C>>А вот partially disconected-приложения как раз очень плохо дружат с классическими БД. S>Может мы под partially disconected разные вещи понимаем? Я вслед за МС и Сеппой под partially disconected понимаю софтину, которая большую часть времени работает автономно и изредка обращается к СУБД за данными/сохраняет изменения.
Да, у меня немного другое.
S>Я не въезжаю, почему СУБД с ними дружить не будет. S>Если вы про приложения с репликацией в локальную in-memory бд — то они зовутся offline clients вообще-то.
Очень часто надо иметь online-изменения, но при этом хранить локальный кэш на клиенте. Такой сценарий получается очень туго.
S>Про репликацию полностью согласен. Тем не менее, какие вы предлагаете варианты по первым двум сценариям (пара удалённых пользователей и филиалы)?
У меня используется моя система когерентных объектных кэшей на клиентах.
Ага. Теперь понял о чём вы. Сгласен. В принципе решаемо и силами СУБД (back notifies через брокер + timestamps на строках), но получается безумно криво и коряво.
Видимо про UI недопоняли друг друга.
Разделяю вашу точку зрения.
S>>>У нас допустим дедлок именно в пропускной способности сети был. G>>При передачи датасетов — я не сомневаюсь. Сам видел такое в одном проекте.
S>У нас не было передачи датасетов. У нас была передача tds от СУБД к клиентам процессор-память простаивали на треть, жёсткий почти на пределе, 100 мбит сеть — фсё (по таск манадждеру ~ 60-70%, по перфмону — дикая очередь пакетов).
Если пытаться вытягивать кучу связанных сущнстей из БД, то это может превратиться в огромную портянку заджойненых данных.
Передача сериализованных объектов бдет экономичнее.
S>>>2) если у вас свой локальный кэш — всё ок. Другое дело, что с ef локальный кэш приходится писать ручками. G>>С чего вы взяли? сам по себе контекст EF обеспечивает локальный кеш. G>>2)Объекты из кеша контекста можно получить так: G>>
G>>from se in context.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged | EntityState.Modified | EntityState.Added)
G>>where !se.IsRelationship
G>>select se.Entity;
G>>
G>>Допилить по вкусу.
S>На выходе имеем мешанину из сущностей различных типов, причём отслеживать изменения в контексте невозможно. Кэш нельзя использовать для удобной выборки локальных данных, для валидации при изменениях и для биндинга. Зачем он нужен в десктоп-клиенте?
.OfType ?
Для биндинга и валидации одной сущности и кеш не нужен. Достаточно одного объекта.
Для графа надо создавать отдельный viewmodel.
Здравствуйте, IB, Вы писали:
VD>>Вань, а что же они у нас то не рулят на сервере? IB>Потому что их там нет, а те что есть — сам знаешь как писались...
Как это нет? Их там хватат. А то что написаны... Ну, так за чем дело встало? Или ты о сфероконях в вакуме рассуждал?
Почему-то в форумах все говорят о каких-то идеальных условиях и лучших реализациях, но в жизни почему-то все время встречаются хреновые условиях и посрдственные реализации.
Мне кажется выбирая стратегию разумнее ориентироваться на второе — на жизнь.
VD>>IT тут недавно рассказывал, что он какой-то там кусок на сервере переписал с использованием линка и скорость выросла в несколько раз. IB>Могу наспор переписать этот же кусок кода на хранимке, чтобы работал как минимум так же (другое дело, что думать придется) и могу придумать такой сценарий, что никакой линк не поможет... Ты это к чему собственно?
Зачем не сапор? Перепиши без споров.
В прочем ты не раз оптимизировал код сервера, но он все равно упорно продолжает тормозить.
Я это говорю не чтобы тебя или твоей подход упрекнуть. Я это к тому, что только на словах все просто. По жизни главная проблема в сложности. А она в не малой мере возникает в следствии того, что код плохо структурирован и используются хреновые средства разработки. IT замечательно продемонстрировал, что с помощью линка и грамотного подхода можно резко увеличить производительность.
VD>>Какое-то расхождение теории и практики. IB>Ты просто не внимательно читаешь. Речь не о хранимка vs линк, а о хранимка vs триггер. Я сам из нашей базы часть триггеров вычищал, лет несколько назад, когда она в очередной раз колом встала.
Как раз к триггерам у меня особых вопросов нет. Главное чтобы там не было бизнес-логики (т.е. много логики).
Кстати, а теперь можно писать триггеры на донтете?
IB>Про линки и запросы из кода — отдельный разговор.
Дык тема как раз про линк и перенос этой логики в хранимки. Причем не в виде продуманного решения, а так чтобы компиляцию устранить.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IB, Вы писали:
VD>> Нужно просто понимать одну простую вещь. MS SQL кэширует планы к запросам очень тупо. IB>Ты даже не представляешь, насколько умно он это делает.. =)
Возможно. А возможно и нет.
Поделись своими мыслями... поглядим.
VD>>Так вот генерируя динамически запросы от вас требуется делать так, чтобы они были одинаковыми. IB>Строго говоря, это не так. Все существенно сложнее и от этих мелочей довольно много зависит.
Понятно, что какие-то там нюансы существуют. Но для понимания общего принципа оно не нужно. А без его понимания люди вот умудряются делая динамические запросы в хранимках получать проигрыш в производительности.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.