XPO

Using .NET Remoting with XPO

In my recent post XPO is good for distributed applications I explained the basics of support for distributed applications in XPO 6.1. This post is going to show how .NET Remoting can be used to make the interface IDataStore available remotely – of course the same approaches can be used to publish ICacheToCacheCommunicationCore instead, if the caching structure is to be used.

The server setup

The setup for a Remoting server can be extremely simple:

  IDataStore dataStore = new DataStoreLogger(new InMemoryDataStore(new DataSet( ),
    AutoCreateOption.SchemaOnly), Console.Out);

  int port = 8880;
  ChannelServices.RegisterChannel(new TcpChannel(port), false);  
  MarshalByRefObject serverObject = (MarshalByRefObject) dataStore;
  RemotingServices.Marshal(serverObject, "DataSetServer");

 Note that in this example, a combination of the DataStoreLogger and the InMemoryDataStore classes is used to implement the server-side data store. This makes for a good test setup, but in a real-world application you would most probably want to replace that with creation code for a more useful data store, like SQL Server:

  IDataStore dataStore = XpoDefault.GetConnectionProvider(
    MSSqlConnectionProvider.GetConnectionString("server", "database"),
    AutoCreateOption.DatabaseAndSchema);
  ...

All data store implementations in XPO implement the interface IDataStore, and all are derived from MarshalByRefObject – the latter is very important to be able to marshal the object as the sample shows, which is why the explicit cast in the sample code makes sure that the given class has the correct ancestor. 

Instantiation

In the sample above, the object in question is being marshalled as a singleton pre-existing instance. This is a good thing if you want to marshal an existing class (that you didn’t create yourself) and the creation logic is somewhat complicated – and of course if you want to use singleton objects server-side. If you want to use a server-activated object (SOA) as a singleton instead, you’d have to create a class that can be instantiated with a default constructor, and make that available as a well-known service type. And you have to override the standard lease time to make sure the object isn’t disposed after a few minutes.

  public class MyDataStore : DataStoreLogger {
    public MyDataStore( ) : base(
      new InMemoryDataStore(new DataSet(), AutoCreateOption.SchemaOnly), Console.Out) { }

    public override object InitializeLifetimeService( ) {
      // make sure the object is never discarded
      return null;
    }
  }

  ...

  // instead of the RemotingServices.Marshal( ... ) call:
  RemotingConfiguration.RegisterWellKnownServiceType(
    typeof(MyDataStore), "DataSetServer", WellKnownObjectMode.Singleton);

Combinations of these approaches are also possible, or per-client instantiation – the point is, XPO doesn’t really have anything to do with this, you can use standard features of .NET Remoting as you see fit.

The client

Assuming we have a server-side singleton that can be directly accessed, like in the samples given above, the client-side code is extremely simple:

  IDataStore dataStore = (IDataStore) Activator.GetObject(typeof(IDataStore),
    "tcp://localhost:8880/DataSetServer");
  XpoDefault.DataLayer = new SimpleDataLayer(dataStore);

The client simply fetches a reference to the data store that the server is publishing (assuming in the sample that the server is running on the same system, but of course “localhost” could be replaced by any other computer name or address) and creates a data layer in the normal way. As usual, all sessions that are now created will use the data layer referenced by XpoDefault.DataLayer by default, effectively accessing the server-side data store through the Remoting connection.

Channels and deployment

In the samples above we have been using the TCP channel all the time. Out of the box, .NET Remoting also includes an HTTP channel and (in .NET 2) an IPC channel for local communication. The IPC channel is not very important here due to its restricted use (which is not to say that it doesn’t work nicely when remoting across AppDomain boundaries), but the HTTP channel is definitely very interesting, because it allows .NET Remoting services to be deployed in IIS. This is in no way XPO specific, I just thought it might be worth mentioning, to show how flexibly .NET Remoting solutions can be deployed.

Creating and registering an HTTP channel is just as easy as the TCP channel in the examples. The HTTP channel uses SOAP formatting by default – it might be a good idea to use binary formatting instead for performance reasons, but be aware that firewalls may sometimes be configured to perform special filtering on SOAP traffic, so binary formatting may not be an option.

This is how you would add an HTTP channel with a binary formatter on the server side:

  Dictionary props = new Dictionary( );
  props["port"] = "8880";
  HttpChannel channel = new HttpChannel(props, null, 
    new BinaryServerFormatterSinkProvider( ));
  ChannelServices.RegisterChannel(channel, false);

And this is the code to add the channel on the client side, and to get the published interface via HTTP:

  ChannelServices.RegisterChannel(
    new HttpChannel(null, new BinaryClientFormatterSinkProvider(), null), false);
  IDataStore dataStore = (IDataStore) Activator.GetObject(typeof(IDataStore),
    "http://localhost:8880/DataSetServer");
  ...

I’m not going to go into the details of deploying to IIS here. There’s a pretty good description available on MSDN: Hosting Remote Objects in Internet Information Services (IIS)

Links

Published Apr 20 2006, 07:44 PM by
Filed under:
Bookmark and Share

Comments

Petros Amiridis

Hi Oliver, does this mean that I can take my current application and move the database connectivity to the server side and then continue using XPO on the client side as usual?
April 21, 2006 1:11 AM

Steven Bartley

I am new to XPO, and this article as well as its predecessor were perfect for me as I intend to use XPO in this manner. Thanks for the kick-start.
April 21, 2006 1:17 AM

Oliver Sturm (DevExpress)

Petros: Yes, it certainly looks like that, doesn't it? :-) Compared to connecting to a database server directly, this can be a very good idea because it introduces an additional layer of abstraction in the form of the Remoting service, which can also be used for other things once it's been established as part of the solution.
April 21, 2006 3:00 AM

Carel Lotz

Oliver

I am bit confused here so please excuse me if this is a stupid question.  What is the actual benefit of using XPO like this?   What does this offer me more than the scenario of XPO v1 where I used XPO with a sql server connection string that pointed to a remote database sitting on another machine?  It seems like the only thing that is being remoted here is the DataLayer and not my actual business objects that inherit from say XPBaseObject.
April 24, 2006 2:28 AM

Oliver Sturm (DevExpress)

Carel,
So, what are benefits of using Remoting instead of direct connections to remote database servers? Let's see what comes to mind:
  • Connecting to databases over any kind of public network is very insecure. The only vendor I remember ever saying that this was a good idea was Oracle, and they were burnt pretty badly. This makes it a good idea to introduce a layer between your client application and the database.
  • Remoting services published over public networks are not inherently secure, but they can be published through (more) trusted systems like IIS and using (more) trusted protocols like SOAP over HTTP, which makes things a lot safer. Of course you can also use security technology on the Remoting level, either using 3rd party products or .NET 2 builtin features.
  • Publishing through IIS brings a number of valuable additional features with it, like SSL encrypted and/or authenticated connections.
  • Using Remoting introduces an additional application layer for you. XPO data layer caching can use this to your advantage, if you publish a central DataCacheRoot object (the interface ICacheToCacheCommunicationCore) via Remoting. Of course you can also extend the new layer with your own functionality and offer more than only the XPO related Remoting service.
  • Of course the new layer also introduces additional abstraction. XPO can already make your application independent from the database backend, but if the clients access just a Remoting service, you can make changes server-side without changing connection strings on all clients or installing additional RDBMS drivers on them.
I'm sure I'm missing something, this is just off the top of my head.

> It seems like the only thing that is being remoted here is the DataLayer and not my actual business objects that inherit from say XPBaseObject.

That's right. That this is so, and why it's a good idea is described in my recent post XPO is good for distributed applications.
April 24, 2006 4:40 AM

Petros Amiridis

Carel, although maybe not the best reason for using remoting, in my case I needed this because I am using Oracle and I must install Oracle Client software in each client computer. Now, normally that would not be a problem. Unfortunately, my client already uses another software from another vendor who had already installed Oracle client software of an older version. Now, I could somehow manage to install the newest Oracle client software without messing with their configuration, but it would be a pain.

Using remoting, solves many problems since I don't have to worry for properly setting up various software components on client side just to be able to talk to the Oracle database server.
April 24, 2006 9:04 AM

Carel Lotz

Oliver,

Am I correct in summarizing the enhancements as being:
1. Security on the data transport layer
2. Ability to use different database versions/DMBS'es at the back-end without affecting the clients
3. Possibility of performance improvements through using server side data caching?

Ito the server side data caching - where can I find more documentation?  How does this link up with the existing cache implemented inside the Session object?  In a remoting scenario, is the client side cache still applicable?  When will it be used?  When will the server side cache be used instead.  Do you need to explicitly code for using the server side cache or does it happen transparently?

Thanks

April 24, 2006 11:05 AM

Oliver Sturm (DevExpress)

Carel,

Sure, that's a summary of what I said. I suspect that people use Remoting for many other reasons, so it's probably not a complete summary.

About data layer caching, I have an explanation of that in another post on this blog: Session Management and Caching. And of course there's information in the help file that comes with XPO - we would like it to be more complete than it currently is and we're working on it, but it's not useless :-)

Short answers to your other questions - I guess these will mostly be answered by that other blog post: data layer caching and the session's object cache are two different technologies with different purposes. Object caching is always in use, data layer caching is optional and needs to be "activated" by using the right classes in your data store chain, other than that it's non-intrusive in 99% of all cases (the 1%, if they are really that many, are the cases where data changes on the server-side are being done by other processes, not using XPO, at the same time as XPO-based data changes).
April 24, 2006 12:42 PM

XPO

First of all, my apologies – I haven’t had time lately to continue the series of posts about...
May 5, 2006 12:04 PM

nayato

hm... But what about any remoting service for objects? Should I forget about object-oriented principles here for the sake of remoting ablity? I'd better to explain:
I think in 3-tiered architecture it is preferable to isolate critical parts of logic pieces like security restrictions or custom (secret) algorithms in Business Logic Layer. In addition it may help to prevent from writing broken code for new clients in future and your server data would be treated in more protected manner. I'd prefer to remain logic encapsulated in objects itself (on the server side) or on the boarder with DAL (here OnXXXing session events). This means that I need to transfer objects itself (disabling logic or providing a kind of remoted logic gate/unit of work) or some kind of its representation (DataTransferObject or DataRow) via Remote Facade. What is actually dissapointing is that this way isn't supported by current architecture of any ORMapper.
Personally I use DTO via Remote Facade on client and objects activated by Remote Facade logic pieces. But in this case XPO features like XPView, XPCollection and others have no sence to me - no serialization support.
Your app-model is suited for Thin (session on server) or Trusted (session on client and non-customizable service with only cache support on server) Clients only.
Do you have any idea on how to treat issues listed above?
July 7, 2006 5:20 AM

Oliver Sturm (DevExpress)

nayato: I don't agree that there's a situation here that XPO (or probably another ORM, for that matter) doesn't support - this is merely a situation where XPO doesn't do anything specific for you. When an application has a number of layers, it is good practice to have each of these layers handle data in formats specific to that layer. Trying to use the same classes (or data formats, more generally) in more than one of these layers frequently results in problems, that's why DTOs are used to transfer data from one layer to another. This is a scenario that XPO definitely supports - we do the same thing through our IDataStore interface, for example, and you are free to do the same thing again on a layer above XPO.

Your problem seems to be that this doesn't happen automatically for you, and of course such a scenario can be complex - the functionality (like XPViews or XPCollections) that's available to you on the XPO layer is no longer there, unless you write it yourself, and any number of classes have to be created to implement the DTOs themselves and the storage classes on the layer above it. This is something that XPO doesn't do for you, but it also doesn't keep you from doing it yourself. You mention the Remote Facade pattern and I think this is the right thing for you to use. But the work of constructing the facade itself with its various methods, and preparing the data for efficient transfer, based on your domain object structure's needs, is not something that is currently done automatically by XPO. As our time allows, we might look into automating this process, but I'm a bit skeptic... also, due to other work, this is probably not something we'll target in the nearest future.
July 10, 2006 5:10 AM

nayato

Well, XPCollection binding features aren't useful at all when it's splitted from presentation layer. You could probably extract common class from it to create a kind of serializable presentation-layer-oriented collection. For now any examples I've seen are running locally (UI is binded to XPCollection) but it is useless in a great number of cases when N-tier architecture is the only choice and where actually ORMs are REALLY needed. It is functionality that have to be done with ORM. There are no good examples or best practices for appliance of XPO in distributed scenario. I'd like to read some remoting-related issues of usage for XPO because I don't need an ORM to build single-module apps with 2-3 interrelated classes. I'd like to know is it ready for complex business solutions with 3 or 4 tiers and hundreds of tables and objects that it should work with.
July 11, 2006 4:21 AM

nayato

I thought of what should XPO provide for remoting ability and it seems to be:
- session unbind/bind for objects and collections
- serialization ability
[- remotable delayed collections]
I understand that it's not so easy to implement these features but it could make XPO actually remotable. And it could be less expensive than building remote facades and DTOs every time you need you object on the other side.
July 11, 2006 5:57 AM

Sergey

Hello!

We had read and learnt help and tutorials about XPO v.6 with its Data Layer and have some question.

We have following task – create 3-tier application – DB-AppServer-Client. In this application, AppServer contains all business-logic(based on persistent objects), accordingly we have thin client. In your examples, which supplied with XPO v.6, all business-logic located on client (in different from our task). How must we use XPO in our case? Of course, we can use XPO only on AppServer, but in this case we must write additional classes-wrappers for transport persistent objects to client. It’s not good idea, because it decrease performance and many other bad stuff may be happened. Moreover, in this case we can’t use XPCollection, which we can very comfortable bind to UI controls (like xtraGrid for example). What can you suggest in this case? Do you have any common scenarios?

Also, we want to clear next things about cache organization on Data Layer level. Is it true, that all DataCacheNode (in runDatSetServerWithLoggedCache.bat example) contains the same cache and DataCacheRoot only manage of synchronization of DataCacheNodes caches? Can we organize hierarchical cache using this classes like picture below:
          CR
          / \
         /   \
       CN     CN     ------ 1 level
             /  \
            /    \
          CN      CN ------ 2 level
where CR – DataCacheRoot, CN – DataCacheNode. And data of cache must be different depending on level – each node cache must contain only data of its clients, and data of caches all children nodes too.
And next technical question is very interest – in which moment of time data in cache will be changed – when occur data updating through DataCacheRoot or after first client application demand data from node?

This article was posted about half of year ago. Can you say what changed in XPO in this time?  On which features do you work? Will it be something about our question?

And one question not only for author, and to all viewers yet – have you any experience of using XPO in distributed application? How positive or negative experience do you obtain while using XPO?  We interest of using XPO in distributed, 3-tier application, where all business-logic concentrated on AppServer.
October 4, 2006 7:23 AM

XPO

Geoff Davis commented on my announcement post: I just don’t get it! Not a problem, Geoff,...
October 16, 2006 10:42 AM

Andrey

Hi, Oliver.
I tried to use Remoting with XPO.

At the server side I wrote such code (like in your sample) :

IDataStore dataStore = XpoDefault.GetConnectionProvider(connection_string, AutoCreateOption.DatabaseAndSchema);

           ChannelServices.RegisterChannel(new TcpChannel(port), false);
           RemotingConfiguration.RegisterWellKnownServiceType(typeof(IDataStore), ObjectUri, WellKnownObjectMode.Singleton);

But: We can pass typeof(IDataStore) to the function RegisterWellKnownServiceType, because IDataStore is not inherited from MarshalByRefObject.
I want to get on a client machine DataLayer, like your sample

XpoDefault.DataLayer = XpoDefault.GetDataLayer("tcp://10.0.0.26:8880/MyServer", AutoCreateOption.DatabaseAndSchema);

How can I pass DataStore of  connection that is specified in connection_string in the code above?
March 16, 2007 8:56 AM

Oliver Sturm (DevExpress)

Hi Andrey
I'm not sure I understand your question, to be honest... you want to use RegisterWellKnownServiceType instead of Marshal? Look at the paragraph titled "Instantiation" in the article above for the difference... RegisterWellKnownServiceType means that the Remoting subsystem handles the instantiation of the type as needed - to do that, of course the type cannot be an interface, because it would be impossible to instantiate that. What's more, you already have an instance created by calling the GetConnectionProvider method. I think you're mixing things up here...
March 16, 2007 9:43 AM

Andrey

Hi, Oliver, thanks for your reply.
You was right, I was mixing two things in my brain.
I have a new question:
In my project, I need to have ability to handling some events of XPO Sessions on the middle-tier(on the server side). In this way I created a class which is inhetited from MarshalByRefObject:
public class MyMarshall:MarshalByRefObject
   {
       public MyMarshall()
       {
       }
       
       IDataStore dataStore;
       public void Connect(string connection_string)
       {
           System.IO.StreamWriter tw = new System.IO.StreamWriter("d:\\work\\myLog.log");
           dataStore = new DataStoreLogger(XpoDefault.GetConnectionProvider(connection_string, AutoCreateOption.DatabaseAndSchema), tw);
       }

       public Session GetSession()
       {
           if (dataStore != null)
           {
               XpoDefault.DataLayer = new SimpleDataLayer(dataStore);
               Session sess = new Session();
               sess.ObjectLoading += new ObjectManipulationEventHandler(sess_ObjectLoading);
               sess.ObjectSaving += new ObjectManipulationEventHandler(sess_ObjectSaving);
               return sess;
           }
           else
               return null;
       }

       void sess_ObjectSaving(object sender, ObjectManipulationEventArgs e)
       {
           //some actions
       }

       void sess_ObjectLoading(object sender, ObjectManipulationEventArgs e)
       {
           //some actions
       }
   }

And like your sample I created a code to pass my object by remoting:

       public static void ConfigureRemoting()
       {
           int port = 8880;
           string ObjectUri = "SpecialServer";
           MyMarshall MarshallObject = new MyMarshall();
           string connection_string=MSSqlConnectionProvider.GetConnectionString("computer", "user", "password", "database");
           MarshallObject.Connect(connection_string);
           ChannelServices.RegisterChannel(new TcpChannel(port), false);
           MarshalByRefObject serverObject = (MarshalByRefObject)MarshallObject;
           RemotingServices.Marshal(serverObject, ObjectUri);
       }


But on the client side there is an error:

MyMarshall ns = (MyMarshall)Activator.GetObject(typeof(IDataStore),
               "tcp://10.0.0.26:8880/SpecialServer");
           Session s= ns.GetSession();
           gridControl1.DataSource = new XPCollection<Person>(s);

Server-sided and the client-sided applications are placed in the separate assemblies, so I added a reference on the client to the assembly of the server to have information about class MyMarshall in each assembly.
But on the last string - "gridControl1.DataSource = new XPCollection<Person>(s);" there occures a FileNotFoundException.
It says that it's  impossible to find a file or assembly "TestRemoting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null". TestRemoting is the client-sided assembly.
What did I do wrong?
How to implement a behavior needed for me.
Sorry for my English.
March 23, 2007 10:55 AM

Oliver Sturm (DevExpress)

Andrey,

To be honest, I'm not surprised that weird things happen in that setup you're using. Basically you're making a Session object available through the remote connection - that's not supposed to happen, the Session class is not to be used for this purpose! Please go back to the "XPO is good for distributed applications" article (link at the top of this page) and read very carefully what is being said about coarse-grained interfaces and IDataStore... in a nutshell it's really simple: use IDataStore as your remote communication interface. That's it.
March 23, 2007 4:24 PM

Andrey

Hi Oliver,
IDataStore interface does not provide functionality of handling any events on server side.
It is very useful for saving objects, bacause we have a capability to create our own logger on the server side.
March 26, 2007 3:23 AM

XPO

SqlDependency is a SQL Server 2005 feature that allows the database server to notify a client when changes

May 16, 2007 11:43 AM

Mad

Hi Oliver!

I have a problem inside the remote client.

On a form the UnitOfWork dies with a RemoteException after a while ("object not connect or disposed")

Can you help me and show me what I'm doing wrong?

I don't use the DataStoreLogger instead I only

use a remote classe.

Inside the remote class I use an Interface having a property

IDataStore DataStore

   {

     get;

   }

==============

inside the server the class looks like this:

 class ServerInfo : MarshalByRefObject, IServerInfo

 {

   public IDataStore DataStore;

   public override object InitializeLifetimeService()

   {

     return null;

   }

   [...]

the server registered the class in this way

     MarshalByRefObject serverObject = (MarshalByRefObject)_serverInfo;

     RemotingServices.Marshal(serverObject, "Datatransfer");

=================

inside the client I use this:

server = (IServerInfo) Activator.GetObject(typeof (IServerInfo), adresse);

       XpoDefault.DataLayer = new SimpleDataLayer(server.DataStore);

p.s. thank you for your great article in dotnet magzine! :-)

best regars,

Mad

October 12, 2007 5:21 AM

XPO

Geoff Davis commented on my announcement post: I just don&rsquo;t get it! Not a problem, Geoff, and certainly

March 28, 2008 2:53 PM

XPO

First of all, my apologies &ndash; I haven&rsquo;t had time lately to continue the series of posts about

March 28, 2008 2:54 PM

Dustin Stejskal 1

I noticed that when the WCF channel faults it wipes out the access layer. It's relatively easy to recognize you have a faulted channel and change the datalayer in XpoDefault.DataLayer. The sessions do not pick up the new datalayer however until you disconnect them. What is the best practice for doing this? Since you can create more than one session, there is no way built-in way of tracking all sessions that are open and disconnecting them/reconnecting them to the new datalayer automatically.

May 21, 2008 4:17 PM

eXpress App Framework Team

This is post no. 10 in the mini series "10 exciting things to know about XAF". You can find

May 31, 2008 11:35 AM

ody

Hi Oliver,

Could you please give us a sample how to use caching in XPO. Because right now I'm looking how to implement XPO in distributed, 3-tier application, where all business-logic concentrated on AppServer.

I'm using devexpress 8.1.

Thank you.

November 12, 2008 11:12 PM

wu cong

Is there any source code?  Thank you

January 5, 2011 7:59 AM
LIVE CHAT

Chat is one of the many ways you can contact members of the DevExpress Team.
We are available Monday-Friday between 7:30am and 4:30pm Pacific Time.

If you need additional product information, write to us at info@devexpress.com or call us at +1 (818) 844-3383

FOLLOW US

DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, along with high-performance HTML JS Mobile Frameworks for developers targeting iOS, Android and Windows Phone. Whether using WPF, ASP.NET, WinForms, HTML5 or Windows 10, DevExpress tools help you build and deliver your best in the shortest time possible.

Copyright © 1998-2017 Developer Express Inc.
All trademarks or registered trademarks are property of their respective owners