:: Не фоксом единым
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
Аспид
если честно, само желание не понятно, ну да лана)
List<adres> adr - это коллекция объектов адрес
т.е. ты можешь получить объект
Adres adres = db.adres.where(p=> p.ID ==1);
Далее в коллекции adr, переписать нужный объект.
На твоем примере
List<adres> adr = db.adres.ToList(); // получаем первоначальный список записей

следующая задача - раз в минуту у меня по таймеру подтягиваются все новые и измененные записи с БД
получаю список новых и измененных записей
List<adres> adrModified = db.adres.where(p=> p.Timestamp > tsTimestamp); // tsTimestamp - это максимальный TimeStamp в локальном списке List<adres>

как его засунуть в существующий List<adres> adr с учетом того, что некоторые ID (записи) там уже есть, а некоторые - новые?
adr.AddRange(adrModified) не работает (должна ли работать - не знаю, я со списками только начинаю разбираться)
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
ВладимирС
Хорошо, когда Entities - простой...
Хорошо когда и таблиц в схеме 3 штуки да связей всего две, и это Book, Purchase да Client Да и то "могут быть нюансы".
ВладимирС
Конечно, может (скорее всего), я плохо разбираюсь в Linq...
По мне, лучше бы запрос написали.
Как связи идут - непонятно.
Да, с линкью "надо разбираться". Само по себе понимание в голову из ноосферы не придёт.
Я бы мог, конечно, посоветовать посмотреть на генерируемый этой штукой SQL запрос, да боюсь что понимания это не добавит
По связям - надо смотреть модель, там будет указано как связаны друг с другом объекты, в т.ч. видно какие поля внешнего ключа и поля первичного ключа отвечают за такую связь со стороны БД. В принципе обычно из модели и так видно это.
В VS подсказки помогут понять что же за q или там p подразумевается в каждом конкретном случае в лямбде.
Хотя понимая параметры каждого метода это и так можно понять. Скажем для твоего примера, по шагам:
c.IndicatorCategorySet // DbSet дающий доступ к объектам некоторого типа. Могу лишь предположить что они класса IndicatorCategory (хотя обычно называют такое свойство IndicatorCategories - т.е. имя класса во множественном числе). Возврат объекта реализующего в частности IQueryable<IndicatorCategory>.
.Single(p => p.Name == category) // Вынимаем ЕДИНСТВЕННЫЙ экземпляр подходящий по условию в лямбде (IndicatorCategory с Name == category) - если таковых более 1 или нет вовсе, то вылет по ошибке. Возврат собственно одиночного объекта IndicatorCategory
.Indicators // доступ к свойству Indicators - судя по всему в модели это коллекция подчинённых объектов (т.е. и есть та самая "связь" между 2-мя таблицами). Возвращает объект IEnumerable<Indicator>
.OrderBy(p => p.Position) // сортируем возвращённый набор Indicator-ов по свойству Position. Возвращает коллекцию Indicator но уже упорядоченную.
.Select( // проекция - т.е. создание нового объекта на основании существующего для каждого элемента из списка. Т.е. для каждого Indicator мы будем делать новый объект.
p => new // новый объект будет анонимным типом - т.е. компилятор сам создаст новый класс со свойствами Id, Caption, ParentId, Unit, Charts
{p.Id, // Id из Indicator пойдёт в Id этого нового объекта.
p.Caption, p.ParentId, // аналогично Id
Unit = // это будет новое "вычисляемое" свойство.
p.Indicators // доступ к свойству Indicators (вероятно объекты Indicator складываются в дерево, т.е. связаны сами с собой определённой иерархией). Могу предположить что это свойство тоже возвращает коллекцию IEnumerable<Indicator> - только уже "подчинённых" нашему обрабатываемому элементу.
.Max(q => // Будем искать максимум для последующего выражения, на основе данных из "подчинённой" IEnumerable<Indicator>
string.IsNullOrWhiteSpace(q.Unit) ? // Если не задано свойство Unit
q.IndicatorRawId.HasValue ? // Если Nullable свойство IndicatorRawId не содержит null
q.Indicator.Unit // Берём из свойства .Indicator (возможно это ссылка на "владеющий" объект Indicator для текущего "подчинённого") свойство Unit
: q.Combinations // Иначе берём свойство Combinations - это тоже какая-то коллекция, судя по имени IEnumerable<Combination>
.Max(r => r.IndicatorRaw.Unit) // Берём максимум по свойству Unit для элементов коллекции IEnumerable<Combination>
: q.Unit), // если задано свойство Unit сразу у "подчинённого Indicator" - его и берём.
Charts = p.Indicators // доступ к свойству Indicators (так же как и выше) для ещё одного "вычисляемого свойства"
.Select(// Опять проекция - т.е. преобразование одних объектов в другие (одной "структуры записи", т.е. "набора полей" в другую).
q => new // и тут анонимный тип
{q.Id, q.ChartType, q.Type, // указанные свойства из "подчинённого Indicator" берём как есть.
Show = // свойство Show вычисляем - оно будет логическим (таков тип выражения ниже).
!q.IndicatorRawId.HasValue // проверка "наличия отсутствия" данных в nullable свойстве IndicatorRawId
|| q.Indicator.Data // Тут ранее не встречавшееся свойство-коллекция Data для "подчинённого Indicator"
.Count(r => r.Category.Type == q.Type) > 1 // Считаем в этой коллекции Data сколько объектов имеют .Category.Type == .Type, если таковых > 1 то true для этой части выражения
&& q.Indicator.Data // Ещё раз смотрим подчинённую коллекцию Data
.Count(r => r.Category.Year >= 2009) > 0 // А теперь считаем сколько объектов имеют .Category.Year >= 2009 и возвращаем true если их > 0. На самом деле тут можно было применить и метод .Any() - нам просто интересно "есть ли хоть один объект удовлетворяющий такому условию" - "считать" число объектов для этого совсем необязательно
}) // Это закончился вложенный Select - он вернул коллекцию анонимных типов со свойствами Id, ChartType, Type, Show
.Where(q => q.Show) // И эту коллекцию мы "прореживаем", выкидывая все элементы которые "не Show"
.ToArray() // А теперь оставшиеся элементы мы превращаем в банальный массив - этим заканчивается вычисление свойства Charts - т.е. там будет массив "анонимных типов" со свойствами Id, ChartType, Type, ну и Show которое всегда true.
}) // Это заканчивается "внешний" Select - он возвращает коллекцию "анонимных типов" с полями Id, Caption, ParentId, Unit, Charts (последнее - это свойство-массив)
.ToList(); // собственно "выполняем запрос", т.е. материализуем всё вышенаписанное. До этого по сути мы "строили логику запроса".

Ну вот как-то так и можно "разбирать" linq конструкции


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
AlexSSS
правильно я понял, что возможности добавить в Code First новых таблиц c помощью визарда нет

Вопрос непонятен...
CodeFirst подход предполагает в идеале:
- нет базы, она будет создана из описания модели (т.е. из описанных бизнес-классов и "контекста").
- база создаётся и изменяется только посредством "миграций" - т.е. опять таки создаваемых на основании модели (классов предметной области типа Person и их контекста) специальных классов, где по сути прописывается какие таблицы создать/удалить/поля_добавить и т.п. В этот код (он генерируется) можно вносить изменения для "уточнения" процесса миграции - скажем то что надо не просто "удалить поле BirthDate и добавить поле Age а перенести инфу при помощи некоторого вычисляемого выражения, ну типа DateTime.Now.Year-BirthDate.Year
- самое важное - код классов предметной области пишется вручную - он НЕ генерируется из БД.
И если с первыми двумя пунктами ещё "есть варианты" (БД можно и вручную создать, если понимать как именно должны называться таблицы и поля, либо в OnModelCreating контекста прописать все "соответствия" между свойствами/классами и таблицами/полями), то желание генерить классы из описаний таблиц - явное противоречие самому подходу "Код СНАЧАЛА"
Вообще не очень понимаю какие там визарды имеются в виду - вроде как на edmx и все эти громоздкие "метаописания" уже давно забили, а для "чисто кода" и Fluent-стиля описания маппинга, или даже атрибутов на свойствах/классах никаких визардов и нет

Аспид
Но начало, неизменно из БД автоматом.
И это ни разу не CodeFirst

AlexSSS
как при таком подходе можно обновить только конкретные записи с базы
Сама инфраструктура для "рефреша" описана по ссылке.
stackoverflow.com
Но лично я не вижу смысла в подобной функциональности. Ни на фоксе я не делал "авторефрешащиеся по таймеру записи", ни на шарпе. Надо юзеру - нажми явно кнопку обновления (тогда когда надо, а не посредине процесса вбивания текста в поле - половину текста вбил, а оно рраз - и зарефрешило эту запись ). И получи не только "новое состояние для 1 записи", а полностью новый список - с добавленными другими юзерами записями, и без удалённых, или без изменённых так что они более не попадают под критерий отбора.
Кстати, сам BindingSource вполне себе можно использовать как "посредник" между контекстом и DataSource всяких гридов.

Теоретически, используя специфические внеSQL-ные функции некоторых серверов БД можно сделать "подписку на событие изменения в БД" - от СУБД зависит гранулярность (ну можно ли подписаться на изменение конкретной одной записи, или набора записей) и собственно возможности. Ну и от провайдеров. Насколько я в курсе "автоматом" это подключить нельзя никуда - ни к датасетам, ни к EF. Да и вообще для такого рода задач гораздо лучше подойдёт написание некоего "сервиса извещений" силами СУБД, или очень близкого к СУБД ПО, нежели просто "уведомления об изменении" от СУБД, и там паче поллинг (тупое перевыполнение запроса по таймеру).

P.S. Ещё вариант - если БД закрыта, т.е. только твоя программа может её менять, то организуй промежуточный слой - сервис через который и будет происходить "общение" клиентов с БД - силами сервиса вполне можно рассылать оповещения о новых/изменённых записях. Лучше при этом не изобретать велосипед а использовать одно из решений на основе MessageQueue, скажем RabbitMQ - там вроде и дока вменяемая и для шарпа "клиентские библиотеки" есть.
Всё прочее - все эти таймеры, шмаймеры - от лукавого

P.P.S. Ну и как бы в общем совет - не научившись строить простейшие "велосипеды", не стоит спешить в автомобиле, и тем паче в авиа-строение
Двунаправленная связь с БД - это достаточно специфическая и above intermediate фишка. Ни разу не для изучающего основы...


------------------
WBR, Igor




Исправлено 2 раз(а). Последнее : Igor Korolyov, 09.08.18 16:24
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
-



Исправлено 2 раз(а). Последнее : AlexSSS, 09.08.18 18:45
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
Igor Korolyov
Ни на фоксе я не делал "авторефрешащиеся по таймеру записи", ни на шарпе. Надо юзеру - нажми явно кнопку обновления (тогда когда надо, а не посредине процесса вбивания текста в поле - половину текста вбил, а оно рраз - и зарефрешило эту запись ). И получи не только "новое состояние для 1 записи", а полностью новый список - с добавленными другими юзерами записями, и без удалённых, или без изменённых так что они более не попадают под критерий отбора.
будем считать, я придумал неудачный пример.

Другой простейший пример, когда мне нужно обновить в локальном источнике только одну конкретную запись
Есть таблица на сервере
Есть такая же локальная таблица (не важно, как она реализована, таблица, список или еще что-то)
Локальная таблица является источником для грида и нескольких контролов, в которых редактируются поля.
Ищу нужную запись в гриде, при нажатии на кнопку Edit мне необходимо обновить в локальной таблице с сервера ОДНУ КОНКРЕТНУЮ ЗАПИСЬ, которую я буду редактировать.
Чтобы на момент начала редактирования я видел актуальную информацию.

Мне не надо тащить всю таблицу с сервера, мне нужно обновить лишь одну конкретную запись.

На форме так же есть кнопка Refresh, по которой мне с сервера в локальную таблицу надо обновить только измененные и новые записи (timestamp > max(localTimestamp)).
И опять же, мне не надо тащить с сервера всю таблицу

Это что, авиастроение?

ps. на датасетах это элементарно решается штатным способом



Исправлено 3 раз(а). Последнее : AlexSSS, 09.08.18 18:48
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
Аспид

Сообщений: 3475
Откуда: Москва
Дата регистрации: 01.04.2005
AlexSSS
Ищу нужную запись в гриде, при нажатии на кнопку Edit мне необходимо обновить в локальной таблице с сервера ОДНУ КОНКРЕТНУЮ ЗАПИСЬ, которую я буду редактировать.
Чтобы на момент начала редактирования я видел актуальную информацию.
Нормальный подход
источником для контролов этой формы формы будет
Adres adres=db.Adreses.where(a=>a.id==id)
Получишь актуальную на момент транзакции данные.
AlexSSS
На форме так же есть кнопка Refresh, по которой мне с сервера в локальную таблицу надо обновить только измененные и новые записи (timestamp > max(localTimestamp)).
И опять же, мне не надо тащить с сервера всю таблицу
А изначально ты притащил всю таблицу?
Просто обновить полностью, с теми же условиями (т.е. полностью заново заполнить таблицу)
Мне кажется это проще, чем манипуляции, в приведенной Игорем ссылке.
Но по идее, что можно.
получить еще один объект того же типа adr.
И сравнивая, заполнить в начальном измененные.
Наверное что то недопонимаю, но я не представляю себе алгоритма иного, либо отправлять на сервер- id,timestamp, и в случае изменения, получать, и заполнять.

Просто не вижу быстрого выхода.
А перезаполнить полностью актуальными данными... мне кажется самое быстрое.

Я как и Игорь, не встречался с такой необходимостью. Даже при очень медленной связи, все равно, большой трафик, позаписное сравнение.
Механизм то от языка не зависит.
У тебя данные на клиенте. А изменения на сервере. Что бы узнать что поменялось, либо все отправить на сервер, и он решит что изменилось, либо получить все на клиента, сравнить, перезаписать... а там, не быстрее ли просто все вывести на экран.

Или все же не понял задачи.
Помнится 1 запись, конкретную хотел поменять, так это не сложно, кажется уже писал)

Igor Korolyov
Ну как всегда, во всем прав)) Отточенная терминология)
Со всем согласен. Просто, я писал на эмоциях) А ты сухо разложил по полкам. ;) В конце концов, все на верном пути)


------------------
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
Аспид
источником для контролов этой формы формы будет
Adres adres=db.Adreses.where(a=>a.id==id)
Получишь актуальную на момент транзакции данные.
чуть изменю вводные - редактирование идет в datagridview, но он настроен так, чтобы редактирование происходило только на одной записи.
И перед редактированием в гриде мне надо обновить только одну конкретную запись.
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
Аспид
Наверное что то недопонимаю, но я не представляю себе алгоритма иного, либо отправлять на сервер- id,timestamp, и в случае изменения, получать, и заполнять.
нее, тут все гораздо проще
вначале я получаю max(timestamp)в локальной таблице.

на сервер идет ОДИН запрос, которые возвращает ВСЕ измененные позже записи
select * from myTable where timestamp>?LocalMaxTimestamp

что надо иметь в виду - при таком способе в локальной таблице останутся висеть записи, которые на сервере уже удалены.



Исправлено 1 раз(а). Последнее : AlexSSS, 09.08.18 20:20
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Это задача нигде не решается "элементарно", поскольку по сути является задачей репликации данных между 2-мя хранилищами.
Проще всего её решать вынимая с сервера полностью "правильный свежий список" по тем же условиям что и шёл изначальный запрос, а потом сопоставлять две "таблицы". Твои таймстампы в общем случае не помогут, т.к. тогда надо:
- запретить удаление (удалённые на сервере записи ты не увидишь т.е. твоя локальная копия будет считать что они всё ещё на месте)
- как-то понять что "обновлённая запись" более не подходит под начальные критерии отбора, и её таки надо убрать из локального кэша (т.е. по сути надо дублировать "логику отбора" - ещё и в коде сопоставления "свежего" и старого состояний).
При этом позаписное извлечение (если ты собирался вдруг рефрешить записи по одной, проверяя в запросе id+timestamp) вообще безумно медленно работает по сравнению с извлечением и обработкой даже 10000 записей но за 1 раз.

Только я ещё раз повторюсь - так не делают. Это бессмысленно. Держать зачем-то локальный кэш, чтобы героически бороться с его устареванием...
Тупо извлёк данные и работай с ними. Надо свежие - снова извлёк, старые выкинул (ну "изменения" вовремя послав на сервер - при вводе, или при нажатии кнопки типа Save). Не надо тебе "обновлять локальный кэш" всякими хитрыми способами. Лишнее это.

P.S. Пока писал ты уже всё и затёр


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
>P.S. Пока писал ты уже всё и затёр
какой-то ответ я заменил уже несколько часов назад, поменяв на более удачную формулировку ;)

Это задача нигде не решается "элементарно", поскольку по сути является задачей репликации данных между 2-мя хранилищами.

код из самого первого сообщения легко и просто это решает
код для обновления одной записи.
if (cTable == "vi_ship")
{
Port.dsPortTableAdapters.vi_ShipTableAdapter ta = new dsPortTableAdapters.vi_ShipTableAdapter();
if (ID == null)
ta.Fill(dsPort.vi_Ship);
else
{
ta.ClearBeforeFill = false;
ta.FillByID(dsPort.vi_Ship, ID ?? 0);
ta.ClearBeforeFill = true;
}
}
аналогично можно сделать метод FillByTimestamp для обновления данных по timestamp

Igor Korolyov
При этом позаписное извлечение (если ты собирался вдруг рефрешить записи по одной, проверяя в запросе id+timestamp) вообще безумно медленно работает по сравнению с извлечением и обработкой даже 10000 записей но за 1 раз.
зачем позаписное?это все решается одним запросом



Исправлено 4 раз(а). Последнее : AlexSSS, 09.08.18 22:12
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
AlexSSS
Ищу нужную запись в гриде, при нажатии на кнопку Edit мне необходимо обновить в локальной таблице с сервера ОДНУ КОНКРЕТНУЮ ЗАПИСЬ, которую я буду редактировать.
Зачем? Пользователь открывает список в 8 утра, а "редактировать запись" будет ближе к вечеру?
Впрочем, если очень надо то это не проблема - код приведен (только не забыть указать ВСЕ объекты требующие рефреша, в т.ч. и подчинённые и коллекции).
AlexSSS
Чтобы на момент начала редактирования я видел актуальную информацию.
Зачем? Если "в процессе редактирования" она с тем же успехом будет изменена "кем-то третьим" на сервере, и к моменту сохранения всё равно будет "отличаться от состояния в локальной таблице"? Конфликты совместного изменения стоит решать именно в момент сохранения, а никак не пытаться их избежать невнятными рефрешами "при начале редактирования строки" - ибо это всё равно не поможет.
AlexSSS
На форме так же есть кнопка Refresh, по которой мне с сервера в локальную таблицу надо обновить только измененные и новые записи (timestamp > max(localTimestamp)).
Зачем? Чтобы получить несовпадающие данные в локальном кэше и на сервере? И в части удалённых записей и в части изменённых, где изменения затронули поля по которым осуществлялся начальный отбор... И в итоге уже через долю секунды после этого рефреша не иметь абсолютно никаких гарантий, что на сервере всё осталось в таком вот виде
AlexSSS
Это что, авиастроение?
Это борьба с ветряными мельницами - вместо того чтобы использовать их для получения муки
AlexSSS
ps. на датасетах это элементарно решается штатным способом
"Это" - это что? датасеты точно так же не дают никаких специальных функций для репликации - они точно так же содержат локальную и заведомо "устаревшую" копию данных. А рефреш делается не сложнее (для датасетов тоже придётся по связанным таблицам ходить и "данные по ссылкам" рефрешить - при том и не новых записей не получить, ни условия начальных ограничений не соблюсти)...

Впрочем, каждый сам себе злобный буратина - придумал ненужную на практике и не реализуемую практически никогда схему работы с данными - ну теперь мучайся с её реализацией


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
Аспид

Сообщений: 3475
Откуда: Москва
Дата регистрации: 01.04.2005
ta.Fill(dsPort.vi_Ship); -- полное обновление
ta.FillByID(dsPort.vi_Ship, ID ?? 0); -- обновление 1й записи.

Не совсем то что просил.

По сути... редактирование в гриде... как то не камильфо...
Ну отредактировал. Сохранил запись, и обновил ее. Именно, и только ее.
Не вижу смысла, тем не менее, по моему, не сложно решается. Хоть на фоксе, хоть на шарпе.

Но это вовсе не обновление по timestamp.
AlexSSS
select * from myTable where timestamp>?LocalMaxTimestamp
Правильно подмечено,
AlexSSS
при таком способе в локальной таблице останутся висеть записи, которые на сервере уже удалены.
А этого мало что бы отказаться?

Ну получил измененные... Нарисуй функцию, которая в объекте list<t> подменяет по id записи (объекты).
Думаю все равно медленнее будет чем получение всего списка.

Или у тебя очень долгое получение списка, и редки изменения, только этим можно объяснить такое желание?


------------------




Исправлено 1 раз(а). Последнее : Аспид, 09.08.18 22:14
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
Аспид
ta.Fill(dsPort.vi_Ship); -- полное обновление
ta.FillByID(dsPort.vi_Ship, ID ?? 0); -- обновление 1й записи.

Не совсем то что просил.
именно это я и просил. И именно это меня полностью устраивало
обрати внимание на
ta.ClearBeforeFill = false;
в случае с одной записью

Аспид
Но это вовсе не обновление по timestamp.
AlexSSS
select * from myTable where timestamp>?LocalMaxTimestamp
Правильно подмечено,
AlexSSS
при таком способе в локальной таблице останутся висеть записи, которые на сервере уже удалены.
А этого мало что бы отказаться?
Проблема с удаленными записями элементарно решается добавлением битового поля isDeleted физическим удалением этих записей скриптом по ночам. ;)



Исправлено 2 раз(а). Последнее : AlexSSS, 09.08.18 22:51
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
Аспид
По сути... редактирование в гриде... как то не камильфо...
редактировать по одной записи в гриде - да, это бред.
Это я просто привел, как пример.
На деле у меня простые формы работают с одним источником (+ другие для связанных таблиц). Пример интерфейса приаттачен
для этой формы есть один основной BindingSource. Он привязан как к гриду, так и контролам.

Переделывать 15 уже готовых форм проекта на то, чтобы для грида использовать один источник, а для расшифрованных данных лругой - нет никакого желания.

пример простой формы
photos.app.goo.gl

что касается вообще редактирования в гриде - для некоторых задач это обалденно удобный для пользователей способ
пример
photos.app.goo.gl



Исправлено 5 раз(а). Последнее : AlexSSS, 09.08.18 23:02
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
обновление одной записи в локальном кэше стандартными средствами решается просто

//BindingSource
public BindingList<Manager> v_Manager = db.Manager.Local.ToBindingList();
//загружаем изначально список всех активных менеджеров
db.Manager.Where(p => p.Obsolete = 0).Load();
// Обновляем в локальном кэше записи по какому-то условию, в данном случае ID == 8
var RowToRefresh = db.Manager.Where(c => c.ID==8);
foreach (var Row in RowToRefresh)
{
db.Entry(Row).Reload();
}
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
хорошая заметка по обновлению локального кэша
codethug.com
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
BindingSource это просто посредник между "настоящим" источником данных (хоть датасет, хоть List<Person> - не имеет значения) и контролами на форме. К работе с данными это не имеет отношения. Собственно говоря, никто и не говорил тебе о том что обязательно надо разные источники использовать. Для одной формы это было бы вообще нелогично - в списке видеть "Вася", а в текстбоксе редактирования "Петя".
Рефреш объекта в контексте обновит именно сам объект - для одной записи в рамках контекста существует всего 1 экземпляр объекта - "материализованной записи". Т.е. он автоматом изменится и в List<T> и в одиночном T. И в каком-нить ещё третьем List<T> где данный объект фигурировал. Другое дело, насколько корректно (со всех точек зрения, но прежде всего для пользователя), к примеру, получив сначала некоторый список через запрос, скажем .Where (x => x.Company=="MS") после такого рефреша получить в списке объект с Company=="Apple"
Я бы сказал что это лажа. И по сравнению с ней попытка поредактировать "старо выглядящий" объект "Вася из MS" и лишь при сохранении получить ошибку, что дескать он уже не Вася и уже не в MS работает - ну как-то логичнее и понятнее выглядит.
Равно и перезапрос - в терминах датасетов "полный и с ClearBeforeFill = true" выглядит проще, логичнее и даже быстрее, чем мытарства с частичным рефрешем по таймстампу дающие лажу для удалённых записей и для изменённых в части критерия отбора...
Я всё же надеюсь что критерий отбора существует, и ВСЯ таблица целиком не извлекается в интерфейс с сервера...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
Igor Korolyov
Я всё же надеюсь что критерий отбора существует, и ВСЯ таблица целиком не извлекается в интерфейс с сервера...
не извлекается. ;)

кстати, одна из вещей EF на эту тему, которая меня сильно порадовала
db.Manager.Find(8) - ищет запись по первичному ключу, если ее нет, то скачивает с сервера.
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
AlexSSS
хорошая заметка по обновлению локального кэша
Да, в том и проблема винформс приложений, что там весьма сложно (хотя и возможно) НЕ держать открытым контекст неопределённо долгое время (собственно говоря это и приводит к проблемам "старья в кэше" - которые приводят к "странностям в очередных запросах"). Для веб проблема не стоит - там открыл контекст, вынул данные, и ЗАКРЫЛ контекст (он не живёт более чем время обработки отдельного HTTP запроса - и как правило это ОЧЕНЬ короткий интервал времени) - а сами данные, обычно ещё и трансформированные отправил в браузер клиенту - то что он там направил, или заново запросил будет работать через НОВЫЙ контекст, где данные будут актуальными. А то что висит на странице - будет висеть бесконечно - до тех пор пока пользователь не начнёт чего-нить тыкать - хоть рефреш, хоть то же редактирование вызывать (если оно отдельно от "списка" таки реализовано).
Там скорее обратная задача стоит, как не долбить базу по 100 раз одними и теми же запросами (для разных клиентов или разных "страниц" по которым ходит один клиент), и хотя-бы пару минут держать всё это в кэше

P.S. твоё стёртое сообщение ярчайший пример бесполезности "рефреша" данных перед началом редактирования
Ну видел я твой текст (актуальное состояние БД на момент начала редактирования), а пока чего-то там думал и писал - оно (состояние в БД) УЖЕ изменилось. Ну и что делать в такой ситуации? И это я ещё не тот же самый элемент данных менял А так - ну вылезла бы ошибка что "некуда уже, мил человек, твои изменения сохранять - запись то, тю-тю". И ничем рефреш не помог...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: c# winforms унифицировать обращение к TableAdapter
AlexSSS
Автор

Сообщений: 6113
Откуда: Tallinn, Estonia
Дата регистрации: 19.09.2005
Igor Korolyov
P.S. твоё стёртое сообщение ярчайший пример бесполезности "рефреша" данных перед началом редактирования
Ну видел я твой текст (актуальное состояние БД на момент начала редактирования), а пока чего-то там думал и писал - оно (состояние в БД) УЖЕ изменилось. Ну и что делать в такой ситуации? И это я ещё не тот же самый элемент данных менял А так - ну вылезла бы ошибка что "некуда уже, мил человек, твои изменения сохранять - запись то, тю-тю". И ничем рефреш не помог...
от этого я и не отказывался ;)
оно есть в сообщениях выше
Цитата:
Ищу нужную запись в гриде, при нажатии на кнопку Edit мне необходимо обновить в локальной таблице с сервера ОДНУ КОНКРЕТНУЮ ЗАПИСЬ, которую я буду редактировать.
Чтобы на момент начала редактирования я видел актуальную информацию.

надо было в самом первом сообщении указать, что я сейчас пишу на WinForms ;)

по факту форма может болтаться открытой с утра до вечера.
какие-то записи могут изменяться несколько раз в день.
редактирование записи редко занимает больше пары минут.
так что вероятность нарваться на то, что кто-то в это время изменил эту же запись крайне мала.

а вот за время, пока была открыта форма - весьма вероятна
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 5 (Гостей: 5)

© 2000-2024 Fox Club 
Яндекс.Метрика