Remote procedure call allows you to run methods on remote PC (or locally). The basic think is simple. All methods you want to run remotelly add into one object (based on BusinessLogic of BusinessLogic.fxp). Then you can use this object to run methods on remote machine. The BusinessLogic object translate all vfp basic types (char,integer,array,bool,...) and cursors for transfer over network. Final result is compressed in memory. For now, no encryption layer is added, but I plan it for the future.
Let we say, that your class seems like this:
define class myClass as businessLogic of businessLogic.fxp
function getCurrentDate
if this.isClient
return this.doRPC()
endif
return date()
function getCursorOrders
if this.isClient
return this.doRPC()
endif
select * from orders into cursor test nofilter
return tmpCursor("test")
* or
* return this.sql("select * from orders")
enddefine
In your main program create the class. Something like
_screen.newobject("BL", "myClass")
From this point, you can use _screen.BL to get results:
? _screen.BL.getCurrentDate()
m.oOrders=_screen.BL.getCursorOrders()
m.oOrders.select
browse
To run it remotelly, you need second instance on remote machine. For playing, just start your VFP session second time. On the second instance (let we say Server) create the same class the same way:
_screen.newobject("BL", "myClass")
_screen.BL.doStartServer( "192.168.1.1", 26272 )
&& Local IP and Port to listen
Now, go back to first instance and tell it to be client:
_screen.newobject("BL", "myClass")
_screen.BL.doStartClient( "192.168.1.1", 26272 )
&& Remote IP and Port to connect
When the client connect to server (.onConnect / .onConnectError), you can use
the class in the same way:
? _screen.BL.getCurrentDate()
m.oOrders=_screen.BL.getCursorOrders()
m.oOrders.select
browse
It is the same code as if it is runned locally, but the method is executed on
remote machine.
.onReply or .onConnectionLost events. During the
.onReply event, return value is stored in .asyncReplyValue.
To switch into asynchronous mode, set
.isAsync=.T.
function cursor_order( orderID, param2 )
if this.isClient
return this.doRPC(@m.orderID, @m.param2)
endif
return this.sql(...)
define class myClass as businessLogic of businessLogic.fxp
* In this example I use sys(2017) to check if record was modified.
* It is not dogma, you can check modified records in other ways,
* or do not check for it and update all.
function cursor_order( orderID )
if this.isClient
return this.doRPC( @m.orderID )
endif
local alias
m.alias="order_"+sys(2015)
select *, cast('' as c(10)) as __crc32__;
from orders;
where orderID=m.orderID;
into cursor (m.alias) readwrite
select (m.alias)
replace all __crc32__ with sys(2017, "__crc32__", 0, 1+2)
return tmpCursor(m.alias)
function save_order( c as tmpCursor )
if this.isClient
return this.doRPC( @m.c )
endif
m.c.select
* todo:
* check values, if incorrect, return .f.
* if new order, assign orderID, ...
* ... follow your database design
* if old, delete unchanged records, ...
delete for __crc32__ == padr(sys(2017, "__crc32__", 0, 1+2), 10)
* now is time to begin transaction or lock files,
* or ... ignore it at all and 'set exclusive on' !
update orders set;
field1=u.field1, ;
field2=u.field2, ;
... ;
from;
(m.c.alias) as u;
where;
orders.rowID = u.rowID
insert into orders (field1, field2, ...) ;
select field1,field2 from (m.c.alias);
where is_New_Record
enddefine
function open_order( orderID )
if this.isClient
return this.doRPC( @m.orderID )
endif
local head, item
m.head="order_header_"+sys(2015)
m.item="order_items_"+sys(2015)
select *;
from orders;
where orderID=m.orderID;
into cursor (m.head) readwrite
select *;
from orders_items;
where orderID=m.orderID;
into cursor (m.item) readwrite
local eo
m.eo=createobject("empty")
=addproperty(m.eo, [head], tmpCursor(m.head))
=addproperty(m.eo, [item], tmpCursor(m.item))
return m.eo
That's all. Hope that it can be usefull. Any comments welcomed. You can ask on the www.foxite.com
MK 2010/11