Cannot perform this operation on a closed dataset error

The application was working perfectly, until I edited the user database (*.dbf) in OpenOffice.org Calc. Now it gives me the above error about a closed dataset.

If you run your application Delphi will restore the open or closed state that the dataset had in the Delphi form designer.

If there is an error Delphi can quitly drop this and close the dataset.
Also it’s possible that you accidently closed the dataset in the designer, after with it no longer auto-opens on ptogram start.
When it’s time to use the dataset you will get this error because the dataset is closed.

One option is to explicitly open the dataset in the FormCreate event and add error handling code there, this will allow you to see the error message and debug from there.

procedure TForm1.FormCreate(sender: TObject);
begin
  try
    MyDBFTable.Open;
  except on exception e do 
    WriteErrorToLogFile('Cannot open MyDBFTable, error is: ' + e.message);
    // or 
    //ShowMessage('Cannot open MyDBFTable, error is: ' + e.message);
  end; {try}
end;

I always do opening of datasets explicitly in FormCreate because this allows me to log any errors. If a client app has an exception it gets emailed to me automatically.

Проблема: При нажатии на кнопку в программе появляется сообщение об ошибке.

Cannot perform this operation on a closed DataSet

Технические детали: На форме есть DataSet (если вы используете компоненты  ADO, тогда это будет ADOQuery, ADOTable, Если UniDac — UniQuery, UniTable… В прочем это не играет большой роли для текущей ситуации). На кнопке был код, который обрабатывал некие данные находящиеся в DataSet’е, при обращении к нему появилась ошибка:

Cannot perform this operation on a closed DataSet


Инструментарий: Delphi XE
Решение: Проблема в том что мы пытаемся обратится к закрытому набору данных DataSet’а, для того чтобы решить данную проблемы пере обращением его нужно открыть.
DataSet.Active
Я к примеру использую процедуру для обновления DataSet’a, если DataSet открыт — обновляем, иначе открываем. Это не универсальное решение, но его можно использовать в большинстве случаев.
procedure RefreshDataSet(DataSet: TDataSet);
begin
if DataSet.Active then
DataSet.Refresh
else
DataSet.Open;
end;

Пример использования:
RefreshDataSet(ADOQuery1);
RefreshDataSet(UniQuery1);

SashaBucheR

0 / 0 / 0

Регистрация: 11.07.2013

Сообщений: 7

1

11.07.2013, 12:07. Показов 50401. Ответов 11

Метки нет (Все метки)


Добрый день! Есть такая проблемка: в наследство досталась программа, которая связывается с SQL сервером. Поставил вместо старого sql 2005 b поменял в ADOConnection путь. Теперь выдает ошибку: cannot perform this operation on a closed dataset (сама программа загружается и данные отображаются, это только когда начинаешь редактировать). В коде есть вот такая ерунда:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
begin
  Application.ProcessMessages;
  sConnection := 'Provider=SQLOLEDB.1;' +
                    'Integrated Security=SSPI;' +
                   // 'Persist Security Info=False;'+
                  //  'User ID=sа;'+
                    'Initial Catalog='+ ConfigParams.FindParam('DATABASE').Value+';'+
                    'Data Source='+ ConfigParams.FindParam('SERVER-GETSQ').Value+';'+
                    'Use Procedure for Prepare=1;'+
                    'Auto Translate=True;'+
                    'Packet Size=4096;'+
                    'Workstation ID='+s+ ';'+
                    'Use Encryption for Data=False;'+
                    'Tag with column collation when possible=False';
end;

Пробовал и Integrated Security и через Юзера, толку нет. Самое интересное, что есть еще программа, которая работает с этой же базой, она работает полностью и редактировать данные можно. Где все-таки косяк? В Делфи или SQL (на сервере проверка подлинности стоит и Windows и SQl)?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



476 / 390 / 111

Регистрация: 24.04.2012

Сообщений: 1,619

Записей в блоге: 3

11.07.2013, 12:31

2

Цитата
Сообщение от SashaBucheR
Посмотреть сообщение

cannot perform this operation on a closed dataset

«невозможно выполнить операцию при закрытом наборе данных», т.е. при редактировании идет обращение к DataSet’у, а он в свою очерез закрыт. А этот код скорее всего с ошибкой никак не связян, т.к. это строка подключения к БД.
Ищи DataSet



0



0 / 0 / 0

Регистрация: 11.07.2013

Сообщений: 7

11.07.2013, 13:37

 [ТС]

3

Я понял, что это строка подключения. Просто думал, что он подключается как-то с ограниченным доступом… Сейчас гляну DataSet. Вот только я слабоват… Нашел где DataSet, а что там проверить, прописать, чтобы он был открыт)
DataSet.Open;?



0



966 / 641 / 97

Регистрация: 01.11.2012

Сообщений: 1,447

11.07.2013, 15:01

4

SashaBucheR, попробуйте у всех Датасетов (ADOTable, ADODataSet, ADOQuery), которые были подключены к вашему ADOConnection изменить свойство Active на значение True.



0



0 / 0 / 0

Регистрация: 11.07.2013

Сообщений: 7

11.07.2013, 15:24

 [ТС]

5

Ошибка "Cannot perform this operation on a closed dataset"

Это во время CreateForm



0



0 / 0 / 0

Регистрация: 11.07.2013

Сообщений: 7

11.07.2013, 15:46

 [ТС]

6

Когда подключаюсь под sa сначала выдает такие две картинки.

Ошибка "Cannot perform this operation on a closed dataset"

Ошибка "Cannot perform this operation on a closed dataset"

А потом опять «cannot perform this operation on a closed dataset»



0



476 / 390 / 111

Регистрация: 24.04.2012

Сообщений: 1,619

Записей в блоге: 3

12.07.2013, 05:12

7

Картинки это конечно хорошо, но еще бы и код немешало бы посмотреть, который их вызывает.



0



SashaBucheR

0 / 0 / 0

Регистрация: 11.07.2013

Сообщений: 7

12.07.2013, 08:45

 [ТС]

8

Выбивает на строке OpenADOTables

Delphi
1
2
3
4
5
6
7
procedure TDM.DataModuleCreate(Sender: TObject);
begin
    ConfigParams := TParams.Create;
    LoadConfig(ExtractFilePath(Application.ExeName)+'config.ini');
    BuildConnection;
    OpenADOTables
end;

Добавлено через 36 минут
cannot perform this operation on a closed dataset например выбивает при создании новой карточки, вот код:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
procedure TfrmCardsIn.NewInvoiceIn;
var
    mR : integer;
begin
    SetEnebledControl(ATYPE);
    DM.tblInvoiceIn.Append;
    DM.tblInvoiceIn['TYPE'] := ATYPE;
    case ATYPE of
    0:
    begin
        DM.tblInvoiceIn['XDSTID']:= '99999';
        DM.tblInvoiceIn['XSRCID']:= '0';
        DM.tblInvoiceIn.FieldByName('GUID').Value := DM.tblInvoiceMax.FieldByName('AMAX').AsInteger + 1;
        DM.tblInvoiceIn.FieldByName('SERIES').Value := DM.tblMaxNumber.FieldByName('SERIES').AsString ;
        DM.tblInvoiceIn.FieldByName('ANUMBER1').Value := DM.tblMaxNumber.FieldByName('ANUMBER').AsInteger  + 1;
        DM.tblInvoiceIn.FieldByName('ANUMBER2').Value := DM.tblMaxNumber.FieldByName('ANUMBER').AsInteger  + 1;
        DM.tblInvoiceIn.FieldByName('ADATE').Value := StrToDate(DM.ConfigParams.FindParam('WorkDate').Value);
        DM.tblInvoiceIn.FieldByName('DSTAMOUNT').Value := 0;
        DM.tblInvoiceIn.FieldByName('SRCAMOUNT').Value := 0;
    end;
    1:
    begin
        DM.tblInvoiceIn['XDSTID']:= '0';
        DM.tblInvoiceIn['XSRCID']:= '0';
        DM.tblInvoiceIn.FieldByName('GUID').Value := DM.tblInvoiceMax.FieldByName('AMAX').AsInteger + 1;
        DM.tblInvoiceIn.FieldByName('SERIES').Value := DM.tblMaxNumber.FieldByName('SERIES').AsString ;
        DM.tblInvoiceIn.FieldByName('ANUMBER1').Value := DM.tblMaxNumber.FieldByName('ANUMBER').AsInteger  + 1;
        DM.tblInvoiceIn.FieldByName('ANUMBER2').Value := DM.tblMaxNumber.FieldByName('ANUMBER').AsInteger  + 1;
        DM.tblInvoiceIn.FieldByName('ADATE').Value := StrToDate(DM.ConfigParams.FindParam('WorkDate').Value);
        DM.tblInvoiceIn.FieldByName('DSTAMOUNT').Value := 0;
        DM.tblInvoiceIn.FieldByName('SRCAMOUNT').Value := 0;
 
        DM.tblMinNumber.Parameters.ParamByName('@SELFDIRID').Value := DM.tblInvoiceIn.FieldByName('XDSTID').AsString;
        DM.tblMinNumber.Open;
        DM.tblInvoiceIn.FieldByName('SERIES').AsString := DM.tblMinNumber.FieldByName('SERIES').AsString;
        DM.tblInvoiceIn.FieldByName('ANUMBER1').AsInteger := DM.tblMinNumber.FieldByName('ANUMBER').AsInteger;
        DM.tblInvoiceIn.FieldByName('ANUMBER2').AsInteger := DM.tblMinNumber.FieldByName('ANUMBER').AsInteger;
        DM.tblMinNumber.Close
    end;
    2:
    begin
        DM.tblInvoiceIn['XDSTID']:= '0';
        DM.tblInvoiceIn['XSRCID']:= '99999';
        DM.tblInvoiceIn.FieldByName('GUID').Value := DM.tblInvoiceMax.FieldByName('AMAX').AsInteger + 1;
        DM.tblInvoiceIn.FieldByName('SERIES').Value := DM.tblMaxNumber.FieldByName('SERIES').AsString ;
        DM.tblInvoiceIn.FieldByName('ANUMBER1').Value := 0;//DM.tblMaxNumber.FieldByName('ANUMBER').AsInteger  + 1;
        DM.tblInvoiceIn.FieldByName('ANUMBER2').Value := 0;//DM.tblMaxNumber.FieldByName('ANUMBER').AsInteger  + 1;
        DM.tblInvoiceIn.FieldByName('ADATE').Value := StrToDate(DM.ConfigParams.FindParam('WorkDate').Value);
        DM.tblInvoiceIn.FieldByName('DSTAMOUNT').Value := 0;
        DM.tblInvoiceIn.FieldByName('SRCAMOUNT').Value := 0;
 
    end;
    3:
    begin
        DM.tblInvoiceIn['XDSTID']:= '0';
        DM.tblInvoiceIn['XSRCID']:= '99999';
        DM.tblInvoiceIn.FieldByName('GUID').Value := DM.tblInvoiceMax.FieldByName('AMAX').AsInteger + 1;
        DM.tblInvoiceIn.FieldByName('SERIES').Value := DM.tblMaxNumber.FieldByName('SERIES').AsString ;
        DM.tblInvoiceIn.FieldByName('ANUMBER1').Value := 0;//DM.tblMaxNumber.FieldByName('ANUMBER').AsInteger  + 1;
        DM.tblInvoiceIn.FieldByName('ANUMBER2').Value := 0;//DM.tblMaxNumber.FieldByName('ANUMBER').AsInteger  + 1;
        DM.tblInvoiceIn.FieldByName('ADATE').Value := StrToDate(DM.ConfigParams.FindParam('WorkDate').Value);
        DM.tblInvoiceIn.FieldByName('DSTAMOUNT').Value := 0;
        DM.tblInvoiceIn.FieldByName('SRCAMOUNT').Value := 0;
 
    end;
 
    end;
 
 
    Mr := frmEditCard.ShowModal;
    if mR = mrOK then
    begin
        try
            DM.tblInvoiceIn.Post;
            case ATYPE of
            0: DM.qryInvoiceIn.Requery;
            1: DM.qryInvoiceReplace.Requery;
            2: DM.qryInvoiceRemove.Requery;
            3: DM.qryInvoiceSpoil.Requery;
            end;
            //(dsCards.DataSet).Refresh;
            dsCards.DataSet.Locate('GUID',DM.tblInvoiceIn['GUID'],[])
        except
            on E: Exception do
            begin
                ShowMessage(E.Message);
                DM.tblInvoiceIn.Cancel
            end
        end;
    end
    else DM.tblInvoiceIn.Cancel
end;



0



476 / 390 / 111

Регистрация: 24.04.2012

Сообщений: 1,619

Записей в блоге: 3

15.07.2013, 09:58

9

а код OpenADOTables?



0



SashaBucheR

0 / 0 / 0

Регистрация: 11.07.2013

Сообщений: 7

16.07.2013, 11:11

 [ТС]

10

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TDM.OpenADOTables;
var
    i : integer;
    Temp : TComponent;
begin
    if ADOConn.Connected then
        for i := ComponentCount - 1 downto 0 do
        begin
            Temp := Components[i];
            if Temp is TADOTable then
            begin
                (Temp as TADOTable).Close;
                (Temp as TADOTable).Open;
            end;
        end;
end;

В том коде, что открытие карточки, я поставил проверку состояния DataSet:

Delphi
1
2
3
4
    If dsCards.DataSet.State = dsInactive Then
      ShowMessage('Close!')
    else
      ShowMessage('Open!');

Выбивает Open, то есть, как бы Dataset активен…



0



Bit_Man

476 / 390 / 111

Регистрация: 24.04.2012

Сообщений: 1,619

Записей в блоге: 3

17.07.2013, 10:03

11

Цитата
Сообщение от SashaBucheR
Посмотреть сообщение

Выбивает на строке OpenADOTables

Если так то проверяй Таблицы после открытия

Delphi
1
(Temp as TADOTable).Open;

Цитата
Сообщение от SashaBucheR
Посмотреть сообщение

выбивает при создании новой карточки

Delphi
1
DM.tblInvoiceIn.Append;

Добавлено через 3 минуты

Delphi
1
DM.tblInvoiceIn.Active

??



0



0 / 0 / 0

Регистрация: 11.07.2013

Сообщений: 7

18.07.2013, 11:39

 [ТС]

12

Там действительно была проблема в таблицах. В ComboBox как-то DataSource сбились. Вот только теперь выдает «Exception class EDatabaseError with message: Circular datalinks are not allowed» при создании формы.

Добавлено через 2 часа 22 минуты
В DataSource не тот Table указал. Теперь все заработало! Спасибо!



0



Roberto Nicchi wrote:

> Il 28/07/2016 02:13, Eivind Bakkestuen [NDD] ha scritto:
> > > I’m wondering how a TnxTable is closed automatically.

> >
> > Afaik, it wouldn’t be.
> >
> > Get the callstacks from your customers and see where it happens;
> > perhaps there’s a clue.
> >

> This is one:
>
> rigdoc_table: Cannot perform this operation on a closed dataset.
>
>
> [007C207D] Data.DB.DatabaseError
> [0044E107] System.SysUtils.AnsiCompareText
> [007D73C1] Data.DB.TDataSet.CheckActive
> [00B3E0A4] nxdb.TnxDataset.CreateBlobStream (Line 8732, «nxdb.pas»)
> [007CE72A] Data.DB.TBlobField.GetAsAnsiString
> [007CF3AC] Data.DB.TMemoField.GetAsString

It looks like your code is attempting to do a field-related function
here before checking the table is active.

……


>
>
> and this is another one
>
> tesdoc_table: Cannot perform this operation on a closed dataset.
>
>
> [007C207D] Data.DB.DatabaseError
> [0080C0F7] JfCollection.TJfCollection.Opt
> [007D73C1] Data.DB.TDataSet.CheckActive
> [007DB7E4] Data.DB.TDataSet.CheckBrowseMode
> [007DAC99] Data.DB.TDataSet.BeginInsertAppend
> [007DA986] Data.DB.TDataSet.Append
> [01E01028] gestione_documenti.attiva_gestione_documenti (Line 1269,
> «gestione_documenti.pas») [02AE516B] main.Tmain_form.esegui_procedura

This one looks like it is trying to do an Append without checking to
see if the dataset is active.


> (Line 3633, «main.pas») [02AEA9E4] main.Tmain_form.JfBitBtn1Click
> (Line 4770, «main.pas») [00657CC3] Vcl.Controls.TControl.Click

……
>
>
> not sure about Nexusdb version. I should add the NexusDb version to
> the Eurekalog report.

You may want to check your table for any dependencies which assume that
the component is active when you open the form. If it’s supposed to be
active then maybe the ActiveRuntime is set to False?


Regards,
Will Owyong
(GMT+10: Newcastle & Parramatta, Australia)

Moderators: gto, EgonHugeist, olehs

marsupilami

Platinum Boarder
Platinum Boarder
Posts: 1699
Joined: 17.01.2011, 14:17

[solved] Cannot perform this operation on a closed dataset

Hello :)

I finally have my first testproject and have a problem. In most of my Projects I use a structure similar to this:

Code: Select all

  ZConnection1.Connect;
  ZConnection1.StartTransaction;
  try
    [do someting]
    ZConnection1.Commit;
  except
    ZConnection1.Rollback;
  end;
  ZConnection1.Disconnect;

With Zeos 7 this raises an exception on commit: «XQuery: Cannot perform this operation on a closed dataset.», where XQuery is a closed query.
When the program subsequently tries to execute the rollback I get the exception «Invalid operation in AutoCommit mode».
Taking a look at the database, I see that the Transaction has been committed. But I wonder why the Connection would do anything to an inactive Query and why it does this after the commit?

This happens with the current version of http://svn.code.sf.net/p/zeoslib/code-0 … es/testing as well as with the latest version of http://svn.code.sf.net/p/zeoslib/code-0/trunk on Delphi XE2 and Firebird 2.1. The transaction isolation level is set to tiReadCommitted.

Best regards,

Jan


marsupilami

Platinum Boarder
Platinum Boarder
Posts: 1699
Joined: 17.01.2011, 14:17

Post

by marsupilami » 13.08.2012, 19:17

Hello,

The problem seems to have resolved itself somehow. :oops:
I am sorry for the trouble…
Best regards,

Jan


patyit

Junior Boarder
Junior Boarder
Posts: 37
Joined: 10.02.2012, 18:39

Post

by patyit » 18.08.2012, 17:04

Hi all !

Jan is lucky, his problem is resolved itself ! :shock:
But mine is not ! :(

Lazarus 1.1, FPC 2.6.0, Zeos svn Testng (also Trunc) latest, Firebird 2.5


Database.StartTransaction;
try
Query1.ApplyUpdates;
Query2.ApplyUpdates;
Query3.ApplyUpdates;

Database.Commit; // <— Error message: ‘External: SIGSEGV’.
except
Database.Rollback;
… // error handling an back to edit data
Exit;
end;
QPrometz.CommitUpdates;
QPromett.CommitUpdates;
QPromet.CommitUpdates;

The full error message is :

Project RobFinPro raised exception class ‘External: SIGSEGV’.

In file ‘/home/patyi/lazarus-svn/zeos7_test/src/component/ZAbstractDataset.pas’ at line 641:
CachedResultSet.DisposeCachedUpdates;

I’m developing an ERP like (big) application and this code construction is very important ! :!:
I found bugreport for this : http://zeosbugs.firmos.at/view.php?id=206
Any progress ?

Best regards, Patyi


ism

Zeos Test Team
Zeos Test Team
Posts: 202
Joined: 02.10.2010, 20:48

Post

by ism » 18.08.2012, 17:26

Lazarus 1.1 ? What you want ?

On older stable versions of the same ?

Lazarus 1.0.8 fpc 2.6.0


ism

Zeos Test Team
Zeos Test Team
Posts: 202
Joined: 02.10.2010, 20:48

Post

by ism » 18.08.2012, 17:27

Lazarus 1.0.8 fpc 2.6.0


User avatar

EgonHugeist

Zeos Project Manager
Zeos Project Manager
Posts: 1936
Joined: 31.03.2011, 22:38

Post

by EgonHugeist » 19.08.2012, 11:44

patyit,

Nope i don’t think there was any further progress. Like i wrote on the BugReport i wanted to have some testers for the added code. I had no time to add a testcase to the testsuites we have. Maybe you can help me here?

Can you determime the SIGDEV?

Ism, he uses the new testing-branch on the other hand it would not be possible to have procedure DisposeCachedUpdates avialable, i think.

Michael


patyit

Junior Boarder
Junior Boarder
Posts: 37
Joined: 10.02.2012, 18:39

Post

by patyit » 19.08.2012, 16:03

ism,
I’m using exactly that rev !

Michael,
I can write a small test application with data to demonstrate and test this bug.
I can test the changes, in test application and on production application with live data.
At least I can tell You it is ok or not.

By now : External: SIGSEGV when try to execute CachedResultSet.DisposeCachedUpdates


patyit

Junior Boarder
Junior Boarder
Posts: 37
Joined: 10.02.2012, 18:39

Post

by patyit » 19.08.2012, 18:27

Some additional information :

I made a test, simulating wrong data witch is cause foreign key violation on ApplyUpdates, the changes is rolled back, and I can edit data correctly to solve the problem. It seams to Rollback is working correctly …


User avatar

EgonHugeist

Zeos Project Manager
Zeos Project Manager
Posts: 1936
Joined: 31.03.2011, 22:38

Post

by EgonHugeist » 19.08.2012, 19:23

patyit,

having a test-case would be fine. For me personally would it be the best help if you are able to add a test to our testsuites directly. So we can test the functionallity allways. However a test case or a patch to fix this issue would be great…

My thougths about the sequence the code should work now:
Take care TZConnection.AutoCommit = False and about the Transaction isolation levels…
try
Query1.ApplyUpdates;
Query2.ApplyUpdates;
Query3.ApplyUpdates; // <— Error message: ‘External: SIGSEGV’. This IS ok for me, if values are missing or the constraint cascade Rules making trouble! Btw. i implemented a TZQuery.Option doUpdateMasterFirst (only available with Zeos) which allows now to update a ForeignKey constraint in the MasterTable first and then all child-Tables.. (Here i allready made some tests and the work nice)

Database.Commit; //IF all Updates are done then this is not neccessary with Zeos if AutoCommit is True on the other hand it should work like expected.. I think this is the issue you want ot point me?!
except
Database.Rollback; //Roleback should dispose all done updates of the RowAccessor and calls DisposeUpdatesCh
… // error handling an back to edit data
Exit;
end;
QPrometz.CommitUpdates; // here i don’t understand you… Database.Commit should do this before.
QPromett.CommitUpdates;
QPromet.CommitUpdates;

Michael


patyit

Junior Boarder
Junior Boarder
Posts: 37
Joined: 10.02.2012, 18:39

Commit error

Post

by patyit » 04.09.2012, 14:46

Hi all !

procedure TZAbstractConnection.Commit;
var
ExplicitTran: Boolean;
i: Integer;
begin
CheckConnected;
CheckNonAutoCommitMode;

ExplicitTran := FExplicitTransactionCounter > 0;
if FExplicitTransactionCounter < 2 then
//when 0 then AutoCommit was turned off, when 1 StartTransaction was used
begin
ShowSQLHourGlass;
try
try
// ***** rem by patyi *****
// for i := 0 to FDatasets.Count -1 do
// THack_ZAbstractDataset(FDatasets).DisposeCachedUpdates;

FConnection.Commit;
finally
FExplicitTransactionCounter := 0;
if ExplicitTran then
AutoCommit := True;
end;
finally
HideSQLHourGlass;
end;
DoCommit;
end
else
Dec(FExplicitTransactionCounter);
end;

I modyfied this procedure and seams to work good with fallowing program construction :

Database.StartTransaction;
try
Query1.ApplyUpdates;
Query2.ApplyUpdates;
Query3.ApplyUpdates;

Database.Commit; // earlier I got Error message: ‘External: SIGSEGV’.
except
Database.Rollback;
… // error handling an back to edit data
Exit;
end;
Query1.CommitUpdates; // this clear cached buffer,
Query2.CommitUpdates; // need because I’m modyfied the
Query3.CommitUpdates; // TZAbstractConnection.Commit procedure

As I said it works good, but I’m not shore about memory leaks …


User avatar

EgonHugeist

Zeos Project Manager
Zeos Project Manager
Posts: 1936
Joined: 31.03.2011, 22:38

Post

by EgonHugeist » 04.09.2012, 20:29

patyit,

ok this a sloution and an example to check the issue. I hope i’ll find the time next week to find out why THack_ZAbstractDataset(FDatasets).DisposeCachedUpdates; does raise exceptions.


User avatar

EgonHugeist

Zeos Project Manager
Zeos Project Manager
Posts: 1936
Joined: 31.03.2011, 22:38

Post

by EgonHugeist » 14.09.2012, 10:38

patyit,

I can do what i want. No way to reproduce the issue.

i use this code:

Code: Select all

procedure TZTestMasterDetailCase.TestClientDatasetWithForeignKey_ApplyUpdates;
var
  SQLMonitor: TZSQLMonitor;
  I: Integer;

  procedure SetTheData(Index: Integer);
  begin
    MasterQuery.Append;
    MasterQuery.FieldByName('dep_id').AsInteger := TestRowID + Index;
    if Connection.UTF8StringsAsWideField or ( Connection.DbcConnection.GetEncoding = ceAnsi) then
        MasterQuery.FieldByName('dep_name').AsString := 'öäüüäö'
    else
      MasterQuery.FieldByName('dep_name').AsString := Utf8Encode(WideString('öäüüäö'));
    MasterQuery.FieldByName('dep_shname').AsString := 'abc';

    if Connection.UTF8StringsAsWideField or (Connection.DbcConnection.GetEncoding = ceAnsi) then
       MasterQuery.FieldByName('dep_address').AsString := 'A adress of öäüüäö'
    else
      MasterQuery.FieldByName('dep_address').AsString := Utf8Encode(WideString('A adress of öäüüäö'));

    CheckEquals(True, (MasterQuery.State = dsInsert), 'MasterQuery Insert-State');
    MasterQuery.Post;

    DetailQuery.Append;
    DetailQuery.FieldByName('p_id').AsInteger := TestRowID + Index;
    DetailQuery.FieldByName('p_dep_id').AsInteger := TestRowID + Index;

    if Connection.UTF8StringsAsWideField or (Connection.DbcConnection.GetEncoding = ceAnsi) then
        DetailQuery.FieldByName('p_name').AsString := 'üäööäü'
    else
      DetailQuery.FieldByName('p_name').AsString := Utf8Encode(WideString('üäööäü'));

    DetailQuery.FieldByName('p_begin_work').AsDateTime := now;
    DetailQuery.FieldByName('p_end_work').AsDateTime := now;
    DetailQuery.FieldByName('p_picture').AsString := '';
    DetailQuery.FieldByName('p_resume').AsString := '';
    DetailQuery.FieldByName('p_redundant').AsInteger := 5;
    DetailQuery.Post;
    CheckEquals(True, (DetailQuery.State = dsBrowse), 'MasterQuery dsBrowse-State');
    CheckEquals(True, (MasterQuery.State = dsBrowse), 'MasterQuery dsBrowse-State');
  end;
begin
  //Connection.AutoCommit := False;
  Connection.TransactIsolationLevel := tiReadCommitted;
  Connection.StartTransaction;
  SQLMonitor := TZSQLMonitor.Create(nil);
  SQLMonitor.Active := True;
  MasterQuery.SQL.Text := 'SELECT * FROM department ORDER BY dep_id';
  MasterQuery.CachedUpdates := True;
  MasterQuery.Open;

  DetailQuery.SQL.Text := 'SELECT * FROM people';
  DetailQuery.MasterSource := MasterDataSource;
  DetailQuery.MasterFields := 'dep_id';
  DetailQuery.LinkedFields := 'p_dep_id';
  DetailQuery.CachedUpdates := True;
  DetailQuery.Open;
  SetTheData(0); //Add 1 line/DataSet
  try
    try
      DetailQuery.ApplyUpdates; //-> crash because of the cascade rules
      MasterQuery.ApplyUpdates;
      Connection.Commit;
      Fail('Wrong ApplayUpdates behavior!');
    except
      SetTheData(1); //Add some more lines
      DetailQuery.Options := DetailQuery.Options + [doUpdateMasterFirst];
      MasterQuery.ApplyUpdates;
      DetailQuery.ApplyUpdates;
      Connection.Commit;
      CheckEquals(True, (MasterQuery.State = dsBrowse), 'MasterQuery Browse-State');
      CheckEquals(True, (DetailQuery.State = dsBrowse), 'DetailQuery Browse-State');
      MasterQuery.SQL.Text := 'delete from people where p_id = '+IntToStr(TestRowID+1);
      MasterQuery.ExecSQL;
      MasterQuery.SQL.Text := 'delete from department where dep_id = '+IntToStr(TestRowID+1);
      MasterQuery.ExecSQL;
    end;
  finally
    MasterQuery.SQL.Text := 'delete from people where p_id = '+IntToStr(TestRowID);
    MasterQuery.ExecSQL;
    MasterQuery.SQL.Text := 'delete from department where dep_id = '+IntToStr(TestRowID);
    MasterQuery.ExecSQL;
    SQLMonitor.Free;
  end;
end;

Waht i’m doing wrong?

Edit:
issue confirmed and is not solvable (Each second cast of the AbstractDataSet uses a pointer to a IZCachedResultSet except DXE2 up) so i’ve added a difine to exclude this code.

Issue is gone. Patch done 1837
Confirmed?


patyit

Junior Boarder
Junior Boarder
Posts: 37
Joined: 10.02.2012, 18:39

Post

by patyit » 20.09.2012, 23:02

Hi EgonHugeist !

I confirmed the issue is gone, at list on Lazarus 1.1, FPC 2.6.1, on XUbuntu,
Win XP and Win 7 tested with my live multiplatform application.
«Unfortunately» I don’t have Delphi (fortunately have Lazarus) that I can’t test under Delphi.

So now I don’t need to call CommitUpdates after Commit ?

Thank for help ! Patyi. :up:


User avatar

EgonHugeist

Zeos Project Manager
Zeos Project Manager
Posts: 1936
Joined: 31.03.2011, 22:38

Post

by EgonHugeist » 21.09.2012, 05:12

patyit,

thank you for confirm the commit behavior.

So now I don’t need to call CommitUpdates after Commit ?

Yes that’s right. CommitUpdates did check the BrowseMode and Clear the Buffer.

Thought the Sequence should be handled like you and others did proprose and in this case CommitUpdates is a deprecated procedure.
Can you post something on Mantis to close this issue?


Через поиск в абд попробовал найти сотрудника. В строке поиска ввёл саба и на экране появилось предупреждение:недопустимое имя столбца саба. Я нажал ок и на экране новое предупреждение Cannot perform this operation on a closed dataset». До этого все работало хорошо. Сталкивались ли с подобным и как решали? 

1 год 5 месяцев назад

avatar

#ссылка

1 ответ

Помогла простая перезагрузка

1 год 5 месяцев назад

avatar

#ссылка

Добавить ответ

Для добавления сообщений на форуме вам необходимо зарегистрироваться и указать мобильный телефон в своем профиле (зачем?)

ЗАДАН

1 год 5 месяцев назад

По каждому вопросу/ответу можно добавлять комментарии. Комментарии предназначены для уточнения вопроса/ответа.

15 hours ago, bazzer747 said:

A suggestion above said to close the query first before opening it and this has worked, so another confusing event here — it cannot work on a closed dataset but after closing it it will open. Who or what closes a dataset? Nothing I do in the application specifically closes any dataset. Many times I respecify the query to change parameters but never knowingly close it.

That might have been me.

Generally, when you change the SQL text, a re-prepare is needed. That cannot be done on an open query. Not your problem above.

When you change the parameter values, the query needs to be re-executed (in a prepared state) and that entails close + re-open.

In a lot of cases the DAC will help you with this (like in a master-detail relationship) and i can confess that back when it took me some time to understand this.

You DAC should offer different ways of handling this, IMHO.

15 hours ago, bazzer747 said:

Who or what closes a dataset?

I cannot answer that (no FireDAC sources), @Uwe Raabe pointed in the right direction.

I would put an event handler on the query’s OnClose and a brekapint in that handler. Then look at the call-stack and put breakpoints below that. Eventually you will find the «culprit».

One more thing, you use a method called «Open» that takes the parameter value as argument. To me that sound like something you do only once.

When the value is changed, some other method should be used. Maybe something like «qQueryname.Refresh([ cYear ] );«. But again, i do not know.

I have a lot of [pseudocode]:

aQ.Params[0].AsInteger := aVar;

if aQ.Open then aQ.Refresh else aQ.Open;

HTH

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Cannot open package error 22
  • Cannot open input device 1 undefined external error
  • Cannot open focusrite usb asio error code 0x54f
  • Cannot open focusrite thunderbolt asio error code 0x54f
  • Cannot open file fsgame ltx сталкер чистое небо как исправить ошибку

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии