Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Apply DiffGram
Message
General information
Forum:
Visual FoxPro
Category:
XML, XSD
Title:
Miscellaneous
Thread ID:
00949029
Message ID:
00949302
Views:
9
Hi Ilmar,

1. You are forcing updates yourself.

Take a look into WHERE statement you are using for UpdateCmd "WHERE USERPK = ?USERS.USERPK", it compares only primary key and there will be no update conflict unless the primary key can't be found. Usually, update conflicts are detected by including a timestamp field or all modified fields or all updatable fields into the WHERE clause. As the set of modified fields varies from record to record, you can use BeforeUpdate/BeforeDelete event to adjust the WHERE clause for a particular record by modifying commands passed to the event handler. Another option, is to let CursorAdapter to generate commands for you, leave InsertCmd/UpdateCmd/DeleteCmd empty and set WhereType property as appropriate. Note, the setting WhereType=4 (DB_KEYANDTIMESTAMP) is not going to work because, in this scenario, CursorAdapter won't know which field is a timestamp field.

2. I am afraid, with the setup you are using for the CursorAdapter object, ApplyDiffgram() won't do the right thing because the InsertCmd/UpdateCmd/DeleteCmd commands use cursor 'Users' as a source for the changes, but the ApplyDiffgram() method treads it as a target and uses temporary created cursor attached to the CursorAdapter object as a source. That temporary cursor is supposed to be referenced by the InsertCmd/UpdateCmd/DeleteCmd instead of the 'Users' cursor, but its Alias is not known until it is attached to the CursorAdapter.
Fortunately, you don't need to use ApplyDiffgram() method at all. After ChangesToCursor() method is called, the 'Users' cursor contains all changes that should be sent to the SQL Server. Just attach this cursor to the CursorAdapter using CursorAttach() method (in this case the 'Users' cursor will be used as a source, exactly as you were planning) and call TABLEUPDATE() function.

Here you can find examples of how to use ApplyDifgram() method: message #787466, message #816987. As I said earlier, you don't need to use it for the current task.

Thanks,
Aleksey.


>It looks like it is still ignoring update conflicts.. (I haven't tried setting the ConflictCheckType to 4 yet)...
>Am I missing something?
>I'm attaching some sample code below. In the situation I have, changes are made to a cursor at the client side, sent as an xml diffgram to the back end where it needs to be applied to an SQL Server table.
>The approach I'm using currently is illustrated below.. but ignores updateconflicts.
>Two questions:
>1. What can I do to catch update conflicts?
>2. Is there a way I can directly apply the diffgram to SQL server, not via Cursor adapters?
>
>-----------------
>ACTIVATE WINDOW debug
>SET STEP ON
>SET MULTILOCKS on
>
>*** FRONT END
>csql = "Select * from users"
>cConnect = "driver=SQL Server;Server=SERVER;Database=MYDATABASE;uid='';pwd=''"
>nHandle = SQLSTRINGCONNECT(cConnect)
>SQLEXEC(nHandle,cSQL,'Users')
>CURSORSETPROP("Buffering" ,5)
>SELECT Users
>BROWSE && modify some data
>
>oxml = CREATEOBJECT('xmladapter')
> With oxml
> .AddTableSchema('Users')
> .IsDiffGram = .T.
> lcSchemaLocation = ''
> lisFile = .F.
> lIncludeBefore =.T.
> lChangesOnly = .T.
> .ToXML('lcXML',lcSchemaLocation,lisFile,lIncludeBefore,lChangesOnly)
> Endwith
> USE IN Users
>oxml = null
>
>**** BACK END
>* now create cursoradapter
>* this would normally happen at the back end:
>oxml = CREATEOBJECT('xmladapter')
>oxml.LoadXml(lcXML)
>loTable = oxml.tables[1]
>
> ca = CREATEOBJECT('ca_users')
> ca.DataSource = nHandle
> ca.ConflictCheckType = 3
>loTable.ChangesToCursor('Users') && this creates a buffered cursor from which the changes will be read
>loTable.ApplyDiffgram('Users', ca) && this always overwrites the current data.. as if Force is on, even if back end data
>* changed in the meantime..
>
>SUSPEND
>Return
>
> Define Class ca_USERS As cursoradapter
> Alias = "USERS"
>
>
> Function Init
> With This
> .KeyFieldList = 'USERPK'
> .Tables = 'USERS'
> .UpdatableFieldList = [USERPK,USERNAME,UPWORD,UVALID,UADMIN,WHPK,ADDDTIME,ADDUSER,EDTDTIME,EDTUSER,USERLEVEL,UEMAIL]
> .UpdateNameList = [USERPK USERS.USERPK,USERNAME USERS.USERNAME,UPWORD USERS.UPWORD,UVALID USERS.UVALID,UADMIN USERS.UADMIN,WHPK USERS.WHPK,]+ ;
> [ADDDTIME USERS.ADDDTIME,ADDUSER USERS.ADDUSER,EDTDTIME USERS.EDTDTIME,EDTUSER USERS.EDTUSER,USERLEVEL USERS.USERLEVEL,UE]+ ;
> [MAIL USERS.UEMAIL]
> .CursorSchema = [USERPK N(10),USERNAME C(25),UPWORD C(25),UVALID I(4),UADMIN I(4),WHPK N(10),ADDDTIME T(8),ADDUSER N(10),EDTDTIME T(8),ED]+ ;
> [TUSER N(10),USERLEVEL N(10),UEMAIL C(100)]
> .cSql = [SELECT USERPK,USERNAME,UPWORD,UVALID,UADMIN,WHPK,ADDDTIME,ADDUSER,EDTDTIME,EDTUSER,USERLEVEL,UEMAIL FROM USERS]
> .SelectCmd = [SELECT USERPK,USERNAME,UPWORD,UVALID,UADMIN,WHPK,ADDDTIME,ADDUSER,EDTDTIME,EDTUSER,USERLEVEL,UEMAIL FROM USERS WHERE USE]+ ;
> [RPK = ?tpk]
> .cWhere = [USERPK = ?tpk]
> .UpdateCmd = [UPDATE USERS SET USERPK = ?USERS.USERPK, USERNAME = ?USERS.USERNAME, UPWORD = ?USERS.UPWORD, UVALID = ?USERS.UVALID,]+ ;
> [ UADMIN = ?USERS.UADMIN, WHPK = ?USERS.WHPK, ADDDTIME = ?USERS.ADDDTIME, ADDUSER = ?USERS.ADDUSER, EDTDTIME = ?USER]+ ;
> [S.EDTDTIME, EDTUSER = ?USERS.EDTUSER, USERLEVEL = ?USERS.USERLEVEL, UEMAIL = ?USERS.UEMAIL WHERE USERPK = ?USERS.USER]+ ;
> [PK]
> .InsertCmd = [INSERT INTO USERS (USERPK,USERPK,USERNAME,UPWORD,UVALID,UADMIN,WHPK,ADDDTIME,ADDUSER,EDTDTIME,EDTUSER,USERLEVEL,UEMAIL) ]+ ;
> [VALUES (?USERS.USERPK, ?USERS.USERNAME, ?USERS.UPWORD, ?USERS.UVALID, ?USERS.UADMIN, ?USERS.WHPK, ?USERS.ADDDTIME, ?USER]+ ;
> [S.ADDUSER, ?USERS.EDTDTIME, ?USERS.EDTUSER, ?USERS.USERLEVEL, ?USERS.UEMAIL)]
> .DeleteCmd = [DELETE FROM USERS WHERE USERPK = ?USERS.USERPK]
> ENDWITH
> DoDefault()
>
> Endfunc
>
> Enddefine
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform