Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2003.09.08;
Скачать: [xml.tar.bz2];

Вниз

Странное при обновлении одной записи двумя пользователями   Найти похожие ветки 

 
AkaSaint   (2003-08-11 23:26) [0]

Сабж в 3-звенном приложении.СУБД MS Jet 4.0, ADO, 2 клиента
непрерывно обновляют записи в таблице из 200 записей. В двух
словах: после обновления записи одним клиентом второй пытается ее
также обновить и получает ошибку (у провайдера стоит
UpdateMode = upWhereChanged, ResolveToDataSet = False.) Второй
клиент обновляет конфликтующую запись с сервера приложений и снова пытается применить свои изменения. И снова получает ошибку, хотя первый клиент эту запись больше не изменял. В OnUpdateError
провайдера видно, что запись не изменяли: текущие значения записи - все пустые. Почему это происходит? Если вам не лень, взгляните на фрагмент протокола происходящего, который пишет сервер приложений.

vasya_p и zebra - имена клиентов.

17:10:01 zebra BeginTrans
17:10:01 zebra Record with OrderNum=82807 is going to be updated
17:10:01 zebra has added updated record with key 82807
17:10:01 zebra Values:
17:10:01 zebra OrderNum= ClientNum= Country=Зимбабве
VisitDate=13.08.2003 Days=8 Nights=7
17:10:01 zebra CommitTrans
17:10:01 vasya_p BeginTrans
17:10:01 vasya_p Record with OrderNum=82807 is going to be updated
17:10:01 vasya_p Ошибка при обновлении atOrders: Изменение: Record not found or changed by another user (код 1)
17:10:01 vasya_p Original (old) record values:
17:10:01 vasya_p OrderNum=82807 ClientNum=462 Country=Юпитер
VisitDate=03.01.2010 Days=10 Nights=103
17:10:01 vasya_p Current values:
17:10:01 vasya_p OrderNum= ClientNum= Country=Зимбабве
VisitDate=13.08.2003 Days=8 Nights=7
17:10:01 vasya_p New values:
17:10:01 vasya_p OrderNum= ClientNum= Country= VisitDate= Days=30
Nights=
<...>//Запрос на освежение изменившихся записей
17:10:01 vasya_p Открыт ADODataSet. Число записей: 11
17:10:01 vasya_p Values:
<...>
17:10:01 vasya_p 9 OrderNum=82807 ClientNum=462 Country=Зимбабве
VisitDate=13.08.2003 Days=8 Nights=7
<...>
17:10:01 vasya_p Клиент (Orders) обновился
17:10:01 vasya_p RollbackTrans
<...>//zebra изменяет другие записи - не 82807
17:10:01 vasya_p BeginTrans
17:10:01 vasya_p Record with OrderNum=82807 is going to be updated
17:10:01 vasya_p Ошибка при обновлении atOrders: Изменение: Record not found or changed by another user (код 1)
17:10:01 vasya_p Original (old) record values:
17:10:01 vasya_p OrderNum=82807 ClientNum=462 Country=Зимбабве
VisitDate=13.08.2003 Days=8 Nights=7
17:10:01 vasya_p Current values:
17:10:01 vasya_p OrderNum= ClientNum= Country= VisitDate= Days=
Nights=
17:10:01 vasya_p New values:
17:10:01 vasya_p OrderNum= ClientNum= Country=Юпитер
VisitDate=03.01.2010 Days=30 Nights=103

Если вы дочитали до этого места - мои вам горячие поздравления :-)


 
Polevi   (2003-08-12 09:41) [1]

F7 пробовал ?


 
Nikolay M.   (2003-08-12 09:47) [2]


> Record not found or changed by another user

Пока не очень хочется вникать в лог и в логику, но поищи в инете, где вылезает эта ошибка для ADO. Для MS SQL такое случается, если есть тригеры, поэтому приходится во всех тригерах писать SET NOCOUNT ON.
Да, и почему у провайдера UpdateMode такой? Если есть первичный ключ, поставь upWhereKeyOnly. Только у Persistent-полей ClientDataSet-а и ADODataSet-а провайдерные флаги правильно выставь, какие - ключ, а что - апдейтить.


 
AkaSaint   (2003-08-12 19:20) [3]

2Polevi: нет, а что это даст?
2Nikolay M. UpdateMode такой, чтобы при попытке изменить те же поля записи, которые успел изменить другой клиент, вылетала ошибка - чтобы клиент понял, что запись была изменена и перечитал ее. Если сделать upWhereKeyOnly, ошибки не будет.


 
Nikolay M.   (2003-08-13 10:15) [4]

1) А как уходят записи? ApplyUpdates (тут сколько?)

2) Что лежит в DataSet события OnUpdateData перед возникновением ошибки?


 
Polevi   (2003-08-13 11:03) [5]

>AkaSaint © (12.08.03 19:20) [3]
это позволит найти тебе место в исходном коде борланда, где эта ошибка возникает, а заодно и решение этой проблемы


 
Polevi   (2003-08-13 11:05) [6]

>Nikolay M. © (12.08.03 09:47) [2]
крайне рекомендую писать это также в хранимых процедурах


 
Nikolay M.   (2003-08-13 11:18) [7]


> Polevi © (13.08.03 11:05) [6]
> крайне рекомендую писать это также в хранимых процедурах

Само собой, но здесь речь идет не о вызове процедуры, а об обновлении таблицы. Поэтому и упомянул только триггеры.
Поправка принята :)


 
AkaSaint   (2003-08-13 12:57) [8]

2Nikolay M. 1)ApplyUpdates(-1)
2) Там лежат старые значения - те, которые этот клиент считал в последний раз.
2Polevi:
>это позволит найти тебе место в исходном коде борланда, где эта >ошибка возникает, а заодно и решение этой проблемы
Хотелось бы, конечно, обойтись без изучения кода Борланда.Изучать чужой код - дело неблагодарное, много требует времени.
Похоже, что ошибка имеет место, когда между попытками 2-х клиентов изменить одну и ту же запись проходит очень мало времени. Изменения, сделанные одним клиентом, несмотря на CommitTrans, еще не успевают вступить в силу. В результате, после появления ошибки, при перечитывании записи могут считаться опять старые данные (это видно из протокола, но не из приведенного мной куска). А могут считаться новые, но все равно что-то не срабатывает... Что?


 
Polevi   (2003-08-13 13:27) [9]

>Изучать чужой код - дело неблагодарное, много требует времени.
Сколько тебе надо времени чтобы изучить данный код ?

Provider.pas


procedure TDataSetProvider.UpdateRecord(Source, Delta: TDataSet; BlobsOnly, KeyOnly: Boolean);
var
Field: TField;
i: Integer;
UseUpMode: TUpdateMode;
begin
if KeyOnly then
UseUpMode := upWhereKeyOnly
else
UseUpMode := UpdateMode;
if not FindRecord(Source, Delta, UseUpMode) then
DatabaseError(SRecordChanged);
...
...
...
end;

function TDataSetProvider.FindRecord(Source, Delta: TDataSet;
UpdateMode: TUpdateMode): Boolean;

procedure GetFieldList(DataSet: TDataSet; UpdateMode: TUpdateMode; List: TList);
var
i: Integer;
begin
for i := 0 to DataSet.FieldCount - 1 do
with DataSet.Fields[i] do
begin
if (DataType in [ftBytes, ftVarBytes]) or IsBlob or
(DataSet.Fields[i] is TObjectField) then continue;
case UpdateMode of
upWhereKeyOnly:
if pfInKey in ProviderFlags then List.Add(DataSet.Fields[i]);
upWhereAll:
if pfInWhere in ProviderFlags then List.Add(DataSet.Fields[i]);
upWhereChanged:
if (pfInKey in ProviderFlags) or (not VarIsEmpty(NewValue)) then
List.Add(DataSet.Fields[i]);
end;
end;
end;

var
i: Integer;
KeyValues: Variant;
Fields: string;
FieldList: TList;
IsDelta: BOOL;
begin
Result := False;
TPacketDataSet(Delta).DSBase.GetProp(dspropISDELTA, @IsDelta);
FieldList := TList.Create;
try
GetFieldList(Delta, UpdateMode, FieldList);
if FieldList.Count > 1 then
begin
KeyValues := VarArrayCreate([0, FieldList.Count - 1], varVariant);
Fields := "";
for i := 0 to FieldList.Count - 1 do
with TField(FieldList[i]) do
begin
if IsDelta then
KeyValues[i] := OldValue else
KeyValues[i] := Value;
if Fields <> "" then Fields := Fields + ";";
Fields := Fields + FieldName;
end;
Result := Source.Locate(Fields, KeyValues, []);
end
else if FieldList.Count = 1 then
begin
with TField(FieldList[0]) do
if IsDelta then
Result := Source.Locate(FieldName, OldValue, []) else
Result := Source.Locate(FieldName, Value, []);
end else
DatabaseError(SNoKeySpecified);
finally
FieldList.Free;
end;
end;


 
Nikolay M.   (2003-08-13 13:58) [10]

Общее замечание, скорее мысли вслух - имхо, не стОит так мучать Access...
Может есть возможность поюзать этот кусок на MS SQL?


 
Nikolay M.   (2003-08-13 14:28) [11]


> Polevi ©

А можно к тебе в аську стукнуться? По ADO и провайдерским флагам как раз на днях непонятки случились...


 
Polevi   (2003-08-13 14:42) [12]

>Nikolay M. © (13.08.03 14:28) [11]
стукнись


 
AkaSaint   (2003-08-16 17:19) [13]

2Polevi: Выглядит и правда не так уж страшно. Но ответа на вопрос все равно не дает.
2Nikolay M. Я бы с радостью не мучал Access, да это все от бедности. Jet Access-то бесплатный, а вот MS SQL - не очень :-) А MSDE можно юзать только при условии не более 5 одновременных подключений, а это очень мало.



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2003.09.08;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.007 c
1-24421
MadGhost
2003-08-26 07:46
2003.09.08
Memo1 продолжение работы.


6-24584
Chaos
2003-07-04 16:46
2003.09.08
Как узнать ср-вами D6 что кто-то подключился к моему компу


6-24573
Samvel
2003-06-27 19:14
2003.09.08
Pageproducer


3-24304
Sirus
2003-08-19 07:31
2003.09.08
Что лучше делать: увеличивать количество записей или ???


6-24571
venoel
2003-07-06 21:41
2003.09.08
Формирование картинки на сервере





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский