Click here to Skip to main content
5,788,961 members and growing! (21,330 online)
Email Password   helpLost your password?
Database » Database » General     Intermediate

Using a Database Over a Webservice

By Tetyana Loskutova

This article shows an example implementation of a database used over a Web-Service
C# 2.0, C#, Windows, .NET, .NET 2.0VS2005, Visual Studio, Architect, DBA, Dev

Posted: 29 May 2007
Updated: 29 May 2007
Views: 12,898
Bookmarked: 31 times
Note: This is an unedited reader contribution
Announcements
Loading...



Search    
Advanced Search
Sitemap
4 votes for this Article.
Popularity: 2.61 Rating: 4.33 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
1 vote, 25.0%
3
1 vote, 25.0%
4
2 votes, 50.0%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

RemotingService project was developed as a simple proof of concept (the idea taken from Database as a Webservice). It is just one more way to realize a remote persistence.

In fact, putting any database on a web-server and providing a remote user interface to it, will realize the same idea from a user point of view. The interesting point of this solution is in the fact that no extra interface is developed, actually database interface is just transferred over the network.

This realization is possible due to the simple object-oriented interface provided by db4o database.

A possible implementation can be in providing personal web-based databases for remote customers. Assuming that each user will use only one and his own database, this solution seems to be viable, providing the data is personally encrypted and unique database names are used.

Background

This article was inspired by Krispy Blog.

Solution Organization

RemotingXml consists of 4 projects:

  • Db4objects.Db4o: db4o open-source database. Please, refer to db4o.license.html for licensing information. The code was slightly modified, which will be discussed later.
  • Server: contains the code for a remote server. Server project is responsible for creating and starting remoting services.
  • RemotingExample: contains the code for creating persistent objects, sending them for serialization to the server and requesting the server for objects from the database.
  • RemotingClasses project is a library containing the definitions for classes to be persisted.

Remoting Classes

RemotingClasses project contains only one test class, which will be used on the client to be stored on the server. The class must have Serializable attribute to be transferrable over the network:
[Serializable]
public class TestValue
{
…
}

db4o Database Amendments

In order to send the persistent classes from the client to the server we will need a Marshal-By-Reference object. This can be any class providing access to an ObjectContainer (can be modified ObjectContainer itself). The requirements to the transport object:

  • the transport object should open a database file on request (filename should be provided somehow);
  • the transport object must have zero-parameters constructor.

With the first implementation I tried to modify the ObjectContainer interface and the implementing classes. However it resulted in quite a lot of modifications as the hierarchy is deep. Moreover, I could not find a logical place to pass a filename to the object container (default implementation requires it in the constructor, and our rules need a parameterless constructor).

In the implementation, provided in this example, I use a version of Db4oFactory class, which can work over the network and can provide ObjectContainers for client requests:

using System;
using System.IO;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;
using Db4objects.Db4o.Ext;
using Db4objects.Db4o.Foundation;
using Db4objects.Db4o.Foundation.Network;
using Db4objects.Db4o.Internal;
using Db4objects.Db4o.Internal.CS;
using Db4objects.Db4o.Reflect;

namespace Db4objects.Db4o
{
    /// <summary>

    /// This class simply duplicates Db4oFactory with 

    /// instance methods, thus allowing Marshalling to

    /// access them

    /// </summary>

    public class Db4oRemoteFactory: MarshalByRefObject
    {
        internal static readonly Config4Impl i_config = new Config4Impl();
        
        public  IConfiguration NewConfiguration()
        {
                    return Db4oFactory.NewConfiguration();
        }

        public IConfiguration CloneConfiguration()
        {
            return (Config4Impl)((IDeepClone)Db4oFactory.Configure()).DeepClone(null);
        }

        public  IObjectContainer OpenFile(string databaseFileName)
        {
            return OpenFile(CloneConfiguration(), databaseFileName);
        }

        public IObjectContainer OpenFile(IConfiguration config, string databaseFileName
            )
        {
            return ObjectContainerFactory.OpenObjectContainer(config, databaseFileName);
        }

    }
}

    

This implementation is convenient for clients working separately. However, it is not suitable for concurrent collaborative work on the same database file.

Another important change to the db4o sources: some of the internal classes representing persistent objects were marked [Serializable] to be suitable for over-network transmission.

Server

The Server project is presented by a single Program class, which role is to start Db4oRemoteFactory service

    class Program
    {
        static void Main(string[] args)
        {
            // Setting up tcp channel

            BinaryClientFormatterSinkProvider clientProvider = null;

            BinaryServerFormatterSinkProvider serverProvider =
                new BinaryServerFormatterSinkProvider();

            serverProvider.TypeFilterLevel =
                System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            IDictionary props = new Hashtable();

            /*
             * Client and server must use the SAME port
             * */
            props["port"] = 65101;
            props["typeFilterLevel"] = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            TcpChannel chan =
                new TcpChannel(props, clientProvider, serverProvider);


            ChannelServices.RegisterChannel(chan);


            Type TestFactory = Type.GetType("Db4objects.Db4o.Db4oRemoteFactory, Db4objects.Db4o");
            RemotingConfiguration.RegisterWellKnownServiceType(
                    TestFactory,
                    "TestFactoryEndPoint",
                    WellKnownObjectMode.Singleton
                );
            Console.WriteLine("TestFactory is ready.");

            // Keep the server running until the user presses

            // the Enter key.

            Console.WriteLine("Services are running. Press Enter to end...");
            Console.ReadLine();
        }
        // end Main


    }

Client

Client project contains Program class. In the constructor a connection to the Db4oRemoteFactory service is established:


      public Program()
        {
            string url;

            // Setup a client channel to our services.

            url = @"tcp://LocalHost:65101/";
            BinaryClientFormatterSinkProvider clientProvider =
                new BinaryClientFormatterSinkProvider();

            BinaryServerFormatterSinkProvider serverProvider =
                new BinaryServerFormatterSinkProvider();

            serverProvider.TypeFilterLevel =
                System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            IDictionary props = new Hashtable();
            props["port"] = 0;
            props["name"] = System.Guid.NewGuid().ToString();
            props["typeFilterLevel"] = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            TcpChannel chan =
                new TcpChannel(props, clientProvider, serverProvider);
            ChannelServices.RegisterChannel(chan);


            // Set an access to the remote proxy

            factory = (Db4oRemoteFactory)RemotingServices.Connect(
                typeof(Db4oRemoteFactory), url + "TestFactoryEndPoint"
                );
        }
        // end Program


The RunTest method creates a test object, sends it to the server using factory and retrieves it from the database on the server:


        private void RunTest()
        {
            // Remote persistent class 

            TestValue testValue;
            testValue = new TestValue();
            // Modify local TestValue object

            testValue.ChangeData("Test value");
            // Pass testValue to the server through testServer

            // and store the testValue object

            IObjectContainer testServer = factory.OpenFile("test.db4o");
            testServer.Set(testValue);
            // Test what is stored to the database

            IList result = testServer.Get(typeof(TestValue));
            //TestValue test;

            foreach (TestValue test in result) {
                System.Console.WriteLine(test);   
            }
        }
        // end RunTest

Points of Interest

  • The most interesting TO-DO on this project is, of course, its performance. How much information is transferred over the network for a single request? How is it comparable to the client-server version of db4o?
  • Are there any advantages over client-server version of db4o?
  • This implementation can only work over tcp-channel. Is it possible to realize the same functionality over html-channel?
  • How to realize concurrency control?

History

2007-05-28 First version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Tetyana Loskutova



Location: United Arab Emirates United Arab Emirates

Other popular Database articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 6 of 6 (Total in Forum: 6) (Refresh)FirstPrevNext
GeneralDb4o's networking featurememberBuu Nguyen19:00 30 Mar '08  
GeneralRe: Db4o's networking featurememberTetyana Loskutova10:08 31 Mar '08  
QuestionLicense issuemember[quad]Cowbe8:41 14 Jul '07  
AnswerRe: License issuememberTetyana Loskutova22:07 14 Jul '07  
GeneralVery usefullmemberMartin Garmendia11:43 29 May '07  
GeneralRe: Very usefullmemberTetyana Loskutova22:02 29 May '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 29 May 2007
Editor:
Copyright 2007 by Tetyana Loskutova
Everything else Copyright © CodeProject, 1999-2009
Web12 | Advertise on the Code Project