Remoting a TypedList

Posts   
 
    
JMichelson
User
Posts: 34
Joined: 27-Dec-2003
# Posted on: 04-Jan-2004 01:35:13   

Hello everyone.

TypedLists are serializable. However, there is not a LLBL constructor for TypedList that will populate the list. So, as I understand it, you have to create the TypedList in one call and then populate it with Fill () in another call.

I'm new to Remoting and easily confused. Once the remote server serializes the class to the client, it is essentially, a local class to that client. So, I guess, calling Fill () after the unpopulated class has been transmitted to the client defeats the purpose of populating the DataTable at the server and THEN sending it to the client. Right?

So... how should TypedList classes be properly remoted - - AFTER they have been populated? Do we need a Factory class to be written at the server?

Thanks. Jeff

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 04-Jan-2004 13:24:39   

Remoting is quite simple: you define a 'channel' using .NET which will transport calls from client to server and data from server to client, transparently.

The best way to start is to define a common interface, as I did in the example I sent you (which is also available online now). This common interface is implemented by the server and used by the client, so the client knows which methods are available on the server and the server knows which methods to implement to make the clients work and be able to call teh server.

You have roughly 2 types of remoting: by reference and by value. By reference means that you hold an object on the client which is a thin proxy for the real object on the server. Each access of a property, each call of a method is transported to the server. This is very 'chatty' and not really an option for scalable systems. The other option, by value, is much more efficient: you call the server, asking the server to give back some object. The server constructs the object, fills it with data and sends it back by returning the object. THe object is transported to the client and lives on the client. The client consumes the object, for example manipulates some data, and for example calls the server again to persist the change by passing the object back to the server. Property access on the client will not result in calls to the server, so this is more efficient.

LLBLGen Pro uses by value remoting, like .NET does too with Datasets. This implies that you create the object on the server, populate it with the data required and return the object. In your situation, you call the server from the client requesting a populated typed list, perhaps passing some values for filters. The method on the server that's called by the client constructs the typed list object, constructs the filter, calls Fill() and returns the typed list object. This is the same as in the example where the client calls the server to return an entity object, the server receives the call, constructs the object, fetches it (this is done in one go by the constructor, but it also could have used FetchUsingPK() or reading a collection and finding the right entity and return that) and returns the object to the client like a normal call would do: return myObject;

Remoting is thus the same as webservices: the remoted server provides a service to the clients. This is a functionality border, you should be able to call the server from the client and get the goods you need by that call, because that's the task for the server: produce the goods, and process the passed back goods (when you want to save an entity for example).

You then also see why the adapter template set is required: an entity object of selfservicing contains a save() method, but it will not be usable on the client, because the client doesn't have access to the database. Adapter's entities don't have these methods, making it more usable in n-tier systems, where abstraction between tiers is required.

If you need more help with this, let me know.

Frans Bouma | Lead developer LLBLGen Pro
JMichelson
User
Posts: 34
Joined: 27-Dec-2003
# Posted on: 05-Jan-2004 07:10:39   

Thanks for the great response. Is there a way that a [Serializable] sample could be posted? I'm having problems getting that to work.

Thanks! Jeff

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 05-Jan-2004 09:56:33   

JMichelson wrote:

Thanks for the great response. Is there a way that a [Serializable] sample could be posted? I'm having problems getting that to work.

Thanks! Jeff

You mean, how to serialize a class to a file or memstream?

Frans Bouma | Lead developer LLBLGen Pro
JMichelson
User
Posts: 34
Joined: 27-Dec-2003
# Posted on: 05-Jan-2004 16:28:25   

You mean, how to serialize a class to a file or memstream?

I'm not sure and I guess that's the real problem. I'm learning C#, remoting and LLBLGen Pro all at the same time. I must admit, that even after reading several books on the subject, the practical relationship between MBR and MBV is confusing to me.

In the sample code that you've posted, you have the following client code:

MarshalByRefObject o = (MarshalByRefObject)RemotingServices.Connect(typeof(Interfaces.IRemoteTest),"http://geek:65100/theEndPoint");

IRemoteTest server = o as IRemoteTest;

CustomerEntity c = server.GetCustomer("CHOPS");

However, your entity and typedlist classes are decorated with [Serializable] and are not inherited from MarshalByRefObject. So, the code necessary to serialize/deserialize an LLBL entity or typedlist is different from the above. I don't know what it is and ALL the posted examples of remoting that I've seen derive from MarshalByRefObject.

I know that this is not, specifically, an LLBL problem. However, for some reason, I find the literature on Serialization to be somewhat confusing because authors seem to focus MUCH more on MBR. So, I appreciate any guidance that you can provide.

Thanks. Jeff

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 05-Jan-2004 17:39:04   

JMichelson wrote:

You mean, how to serialize a class to a file or memstream?

I'm not sure and I guess that's the real problem. I'm learning C#, remoting and LLBLGen Pro all at the same time. I must admit, that even after reading several books on the subject, the practical relationship between MBR and MBV is confusing to me.

If you just think of reference types and value types it's perhaps a bit more clear simple_smile MBR is giving you a reference to a remote object, thus an instance running on a remote server. You control that object via a proxy object on the client, and the client thinks its manipulating / accessing the real object but in reality its actions are send to the server and replayed there. MBV is not using this technique, the client has the actual object (or better, a re-incarnation of the object created on the server), the server doesn't.

In the sample code that you've posted, you have the following client code:

MarshalByRefObject o = (MarshalByRefObject)RemotingServices.Connect(typeof(Interfaces.IRemoteTest), "http://geek:65100/theEndPoint");

IRemoteTest server = o as IRemoteTest;

CustomerEntity c = server.GetCustomer("CHOPS");

However, your entity and typedlist classes are decorated with [Serializable] and are not inherited from MarshalByRefObject. So, the code necessary to serialize/deserialize an LLBL entity or typedlist is different from the above. I don't know what it is and ALL the posted examples of remoting that I've seen derive from MarshalByRefObject.

Serialization is the technique used to convert an object from an instance to a stream of data, like an ascii stream or a binary stream, which then can be saved into a file, or transported over a wire. If you decorate a class with [Serializable], .NET will try to serialize the object itself using a ghost class. This will often work. Sometimes it doesn't and you have to implement ISerializable, and do the serialization yourself. That's what the framework does for you, I've written all that code inside the runtime libraries and partly in the templates. So the classes are serializable and will be serialized sometimes directly by .NET, and sometimes by my code if .NET can't do it by itself (for example if a class defines eventhandlers, .NET's serializers get confused).

With remoting, the serialization/deserialization part is transparent for you. In the snippet above, you see a creation of the remoted object that runs on the server. It's marshalled by reference so the client holds a proxy object which calls the actual object in the server. The code then does: CustomerEntity c = server.GetCustomer("CHOPS"); GetCustomer is a call of the proxy's method GetCustomer and this call is 'marshalled' (transfered to another process, including conversion of data) to the actual object, living on the server. That object on the server has a GetCustomer method, and that method is then called. This method returns a value, a CustomerEntity. When the method on the server does that, the result is 'marshalled back' to the client, or better: to the proxy object the client works with (the object 'server' references). This marshalling is done via SOAP. The data transfered back and forth is serialized to xml in SOAP format, then send to the other end and there Deserialized into an instance. The proxy object on the client thus deserializes the received Xml send by the remoted object (which is done transparently by the channels build in .NET) into a CustomerEntity instance and returns that as the result of teh server.GetCustomer() call. The client then has a real reference to a real object which solely lives on the client.

simple_smile

Frans Bouma | Lead developer LLBLGen Pro
JMichelson
User
Posts: 34
Joined: 27-Dec-2003
# Posted on: 06-Jan-2004 08:51:48   

Ok, yes... I get it. You would presume that developers would write server classes that inherit the MarshalByRefObject and implement an IEntityFactory or ITypedListFactory which, in turn, create the LLBLGen Entities or TypedLists. The client creates a proxy for that interface and then receives a copied Entity or TypedList BECAUSE LLBL decorates all objects with the [Serialiable] attribute.

Right?

Q: Would this work if the server was hosted by IIS as well as in custom server applications?

Thanks again for your support. I don't know which is better... your product or your customer care!

Jeff