Бд состоит из 3х связанных таблиц.
1аф зависит от 2ой и 2ая от 3ей.
В проекте имеется DataSet — в котором эти связи настроены.
Заполняю DataSet следующим образом:
public DataSet FillDispDataSet(DataSet DispDataSet)
{
// Используемые переменные
OleDbConnection conn;
// Дата адаптеры
OleDbConnectionStringBuilder cb;
cb = new OleDbConnectionStringBuilder();
cb.FileName = AppDomain.CurrentDomain.BaseDirectory + @"\DBDispLocal.udl";
conn = new OleDbConnection(cb.ToString());
OleDbCommand selObjects = new OleDbCommand("SELECT * FROM OBJECTS ORDER BY ID", conn);
OleDbCommand selPoints = new OleDbCommand("SELECT * FROM POINTS ORDER BY ID", conn);
OleDbCommand selNetInfo = new OleDbCommand("SELECT * FROM NETINFO", conn);
try
{
// Очищаем ДатаСет
DispDataSet.Tables["NETINFO"].Clear();
DispDataSet.Tables["POINTS"].Clear();
DispDataSet.Tables["OBJECTS"].Clear();
// создаем дата-адаптеры
daObjects = new OleDbDataAdapter(selObjects);
daPoints = new OleDbDataAdapter(selPoints);
daNetInfo = new OleDbDataAdapter(selNetInfo);
OleDbTransaction dbTrans;
DataSet DispDB = DispDataSet;
// открываем базу
conn.Open();
dbTrans = conn.BeginTransaction();
selObjects.Transaction = dbTrans;
selPoints.Transaction = dbTrans;
selNetInfo.Transaction = dbTrans;
daObjects.Fill(DispDB, "OBJECTS");
daPoints.Fill(DispDB, "POINTS");
daNetInfo.Fill(DispDB, "NETINFO");
dbTrans.Commit();
conn.Close();
return DispDB;
}
catch (OleDbException myOLEDBException)
{
OLEDBExceptionReport(myOLEDBException);
return DispDataSet;
}
catch (Exception myException)
{
ExceptionReport(myException);
return DispDataSet;
}
}
Иногда данные в базе обновляются и в потоке я запрашиваю приведенную выше процедуру, я хватаю или exception, или заполняются таблицы не полностью, 1ая("OBJECTS") так вообще пустой остается.
Никак не могу понять в чем ошибка.
Т.к. при запуске программы например — происходит однокртаный вызов данной процедуры — все работает нормально.
Здравствуйте, ZeeM, Вы писали:
ZM>Проблема следующая
ZM>Иногда данные в базе обновляются и в потоке я запрашиваю приведенную выше процедуру, я хватаю или exception, или заполняются таблицы не полностью, 1ая("OBJECTS") так вообще пустой остается. ZM>Никак не могу понять в чем ошибка.
Что это "и в потоке я запрашиваю приведенную выше процедуру, я хватаю или exception" значит ? Создаешь новый поток (thread) и вызываешь метод уже из контекста созданного потока ?
ZM>Т.к. при запуске программы например — происходит однокртаный вызов данной процедуры — все работает нормально.
Здравствуйте, Igor Sukhov, Вы писали:
IS>Здравствуйте, ZeeM, Вы писали:
ZM>>Проблема следующая
ZM>>Иногда данные в базе обновляются и в потоке я запрашиваю приведенную выше процедуру, я хватаю или exception, или заполняются таблицы не полностью, 1ая("OBJECTS") так вообще пустой остается. ZM>>Никак не могу понять в чем ошибка.
IS>Что это "и в потоке я запрашиваю приведенную выше процедуру, я хватаю или exception" значит ? Создаешь новый поток (thread) и вызываешь метод уже из контекста созданного потока ?
ZM>>Т.к. при запуске программы например — происходит однокртаный вызов данной процедуры — все работает нормально.
Так все и делаю. Скорей всего проблема в том что DataGridView в котором отображается DataSet, ловит экзепшн, при изменении DataSeta.
Как его безопасно обновлять?
Здравствуйте, ZeeM, Вы писали:
ZM>>>Иногда данные в базе обновляются и в потоке я запрашиваю приведенную выше процедуру, я хватаю или exception, или заполняются таблицы не полностью, 1ая("OBJECTS") так вообще пустой остается. ZM>>>Никак не могу понять в чем ошибка.
IS>>Что это "и в потоке я запрашиваю приведенную выше процедуру, я хватаю или exception" значит ? Создаешь новый поток (thread) и вызываешь метод уже из контекста созданного потока ?
ZM>>>Т.к. при запуске программы например — происходит однокртаный вызов данной процедуры — все работает нормально.
ZM>Так все и делаю. Скорей всего проблема в том что DataGridView в котором отображается DataSet, ловит экзепшн, при изменении DataSeta. ZM>Как его безопасно обновлять?
А как сделать уведомление основному потоку?
Получается что в основном потоке у меня зарегестрировано событие — и в обработчике этого события я как раз изменяю DataSet. Т.е. мне как-то необходимо уведомлять основной поток о том что в обработчике события что-то сделалось и обновить DataSet. Как это реализвоать?
Здравствуйте, ZeeM, Вы писали:
IS>>Обновляй DataGridView из основного потока.
ZM>А как сделать уведомление основному потоку? ZM>Получается что в основном потоке у меня зарегестрировано событие — и в обработчике этого события я как раз изменяю DataSet. Т.е. мне как-то необходимо уведомлять основной поток о том что в обработчике события что-то сделалось и обновить DataSet. Как это реализвоать?
Несколько сумбурно объясняешь — я мало что понял из твоих пояснений. Если причина этой ошибки в потоко-зависимой природе grid-a,
то для обновления данных в нем используй метод Invoke который grid отнаследовал от Control-a.
Из другого потока вызываешь метод Invoke у объекта grid-a. В него передаешь делегат — "указывающий" на метод который будет исполняться
в основном потоке, и массив состящий из двух элементов — сам grid и DataSet содержаший новый данные для него.
В теле метода достаешь из массива и grid и DataSet. Присваиваешь свойству DataSource grid-a ссылку на DataSet.
Но как я сказал — из твоего объяснения мало что понятно. Понятно одно — раз у тебя код работает в первый раз (при запуске программы и начальном заполнении grid-a) —
то делай в точности тоже самое когда тебе нужно обновлять данные — и все будет работать.
Здравствуйте, Igor Sukhov, Вы писали:
IS>Здравствуйте, ZeeM, Вы писали:
IS>>>Обновляй DataGridView из основного потока.
ZM>>А как сделать уведомление основному потоку? ZM>>Получается что в основном потоке у меня зарегестрировано событие — и в обработчике этого события я как раз изменяю DataSet. Т.е. мне как-то необходимо уведомлять основной поток о том что в обработчике события что-то сделалось и обновить DataSet. Как это реализвоать?
IS>Несколько сумбурно объясняешь — я мало что понял из твоих пояснений. Если причина этой ошибки в потоко-зависимой природе grid-a, IS>то для обновления данных в нем используй метод Invoke который grid отнаследовал от Control-a.
IS>Из другого потока вызываешь метод Invoke у объекта grid-a. В него передаешь делегат — "указывающий" на метод который будет исполняться IS>в основном потоке, и массив состящий из двух элементов — сам grid и DataSet содержаший новый данные для него.
IS>В теле метода достаешь из массива и grid и DataSet. Присваиваешь свойству DataSource grid-a ссылку на DataSet.
IS>Но как я сказал — из твоего объяснения мало что понятно. Понятно одно — раз у тебя код работает в первый раз (при запуске программы и начальном заполнении grid-a) — IS>то делай в точности тоже самое когда тебе нужно обновлять данные — и все будет работать.
Обновление пробовал делать потокобезопасным. Через InvokeRequired.
Дело в том что изначально — в дизайнере еще, я привязываю к гридам свой DataSet. Т.е. автоматически при изменение датасета грид тоже обновляется. Как перехватить это изменение? Чтобы сделать его потокобезопасным.
Здравствуйте, ZeeM, Вы писали:
ZM>Обновление пробовал делать потокобезопасным. Через InvokeRequired. ZM>Дело в том что изначально — в дизайнере еще, я привязываю к гридам свой DataSet. Т.е. автоматически при изменение датасета грид тоже обновляется. Как перехватить это изменение? Чтобы сделать его потокобезопасным.
Как реализовать потокобезопасные изменения — я уже написал. Что такое "перехватить изменеия" — я не понял.
Напиши в общих чертах — как и что у тебя работает и как должно работать и когда не работает. По шагам.
А то вот уже несколько гридов появилось — а я про это ничего не знал.
Есть датасет в котором содержится три связанные таблицы.
Есть 3 грида, в кажом из которых отображается одна из таблиц.
В дизантайме к каждому из гридов я привязал соответствующую таблицу.
Далее во время работы программы приходит событие в котором изменяется датасет. В результате при изменении датасета автоматически должны меняться отображаемые данные в гридах. При изменении датасета я и ловлю экзепшн.
Насколько я понимаю, надо как-то отлавливать момент когда происходит обновление данных в гридах. Как это сделать?
1) Изменение датасета в основном потоке работает нормально
2) Я пробовал во время изменения датасет повторно прикручивать датасет к гридам потокобезопасно. Но все равно падает экзепшн, т.к. похоже грид дополнительно обновляется сам из привязанного датасета.
Здравствуйте, ZeeM, Вы писали:
ZM>Далее во время работы программы приходит событие в котором изменяется датасет. В результате при изменении датасета автоматически должны меняться отображаемые данные в гридах. При изменении датасета я и ловлю экзепшн.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, ZeeM, Вы писали:
ZM>>Далее во время работы программы приходит событие в котором изменяется датасет. В результате при изменении датасета автоматически должны меняться отображаемые данные в гридах. При изменении датасета я и ловлю экзепшн.
L>Делай это изменеие в UI-потоке.
А как мне уведомить UI поток что у меня изменился DataSet?
Изменяется он в обработчике приходящего события.
Здравствуйте, Greeter, Вы писали:
G>А не в ConstraintException ли проблема? G>Просто так заливать-выливать данные из датасета нельзя, если определены какие-то констрейнты. Делаем так:
G>
G>try
G>{
G> dataSet.EnforceConstraints = false;
G> // Обновляем набор данных - заполняем таблицы адаптерами и т.д.
G>}
G>finally
G>{
G> dataSet.EnforceConstraints = true;
G>}
G>
Проблема точно не в этом. Я делал обновление датасет в основном потоке вручную — все работает нормально. Проблема при обновлении в не UI потоке.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, ZeeM, Вы писали:
L>>>Делай это изменеие в UI-потоке.
ZM>>А как мне уведомить UI поток что у меня изменился DataSet?
L>Не нужно уведомлять UI-поток. Нужно изменение делать в UI-потоке.
ZM>>Изменяется он в обработчике приходящего события.
L>
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Igor Sukhov, Вы писали:
IS>>то для обновления данных в нем используй метод Invoke который grid отнаследовал от Control-a.
AVK>AsyncOperationManager более кошерен с точки зрения архитектуры.
может быть, может быть. Спасибо — не знал про такой класс.
Но в данном случае — чем проще (Invoke) тем лучше.