We’ve been looking at the way to efficiently store a lis of quotes some time ago. And Steve suggested that if we’re to store a gian number of quotes, we may look into some misterious being called ObjectStore…

If there will be many qoutes, e.g. you buy a “100.000 quotes of the day” database, you might want to put them into a separate table in the database. Seasoned EPiServer developers tend to think that everything can be stored as pages in EPiServer, which is kind of true, but not necessarily wise.

Another option could be to store the quotes in the ObjectStore, the general EPiServer storage feature, which can hold about anything you’d like, efficiently, quickly restorable, searchable, indexable, highly available and environmentally safe. It might even solve the global warming problem while we’re at it. Ok, maybe not. Truthfully, only a few developers outside of EPiServer know how to use it, and quite alot of us inside have no clue whatsoever. But, the tales I’ve heard about it would nominate it as a prime candidate for a quote system like this. Right now, it is storing things like XForms definitions and data, WSRP stuff, Content Mirroring data and lots more. It’s been around since 4.50 (I think) and is said to be documented – eventually, until then I guess we’ll have to resort to other ways of doing things.

MmmMmm… tasty!

Research mode “ON”.

There is no documentation, allright, but there is Reflector. Between the reflector and the sample server, there can be no secrets that can hide form us :)

Basically the ObjectStore is a way of persisting any serializable object (with some minor adjustments).

  • Object store is divided into Schemas.
  • A schema seems to be way of grouping types of objects into easily manageabble pools
  • A class type has to be contained within a schema to be persisted.
  • A type needs to be registered within a schema before you can write to it.
  • A type needs to implement EPiServer.BaseLibrary.IItem interface and be marked as Serializable for the ObjectStore to be able to serve it.

The Research Field

The namespaces of your interest is EPiServer.BaseLibrary, namely the following parts of it:

namespace EPiServer.BaseLibrary
{
public sealed class Context
public interface IContext
public interface IItem
public interface IItemList : IEnumerable
public interface IObjectStore
public interface IRepository
public interface ISession
}

Then you may want to open EPiServer.XForms.XFormData and EPiServer.XForms.XForm especially the Save() method of the latter is very educating.

The code for the ObjectStore implementation lives in the EPiServer.Implementation namespace but having all the interfaces exposed its implementation details should not be of our concern. Suffice to say itseems to be flexible ane extensible. You can have it sitting on an Oracle & Microsoft SQL Server databases as well as having it stored In an XML file. I assume there would not be much trouble replacing the object store looking as the Logging service has it setup dynamically through settings in its config file.

The results

  • The class you want to persist should inherit IItem and be serializable.
  • The default repository is stored in the Context and is capable of creating more sessions for us
  • Bah, enough of the bulleted lists… let the code speak for itself…

using System;

using System.Collections.Generic;

using System.Text;

using EPiServer.Implementation;

using EPiServer.Implementation.Serialization;

using EPiServer.BaseLibrary;

using System.Xml.Serialization;

 

namespace Cognifide.EPiServerTest.ObjectStore

{

    [Serializable, XmlInclude(typeof(CogObjectStoreItem))]

    public class CogObjectStoreItem : IItem

    {

 

        string data;

        private object id;

        private string name;

 

        public object Id

        {

            get { return this.id; }

            set { this.id = value; }

        }

        public string Name

        {

            get { return this.name; }

            set { this.name = value; }

        }

 

        public CogObjectStoreItem(object id, string name, string data)

        {

            this.data = data;

            this.id = id;

            this.name = name;

        }

 

        public void Save()

        {

            ISession session = null;

            try

            {

                // check if there is a schema for the type, if not create it.

                if (Context.Repository.SchemaForType(this.GetType()) == null)

                {

                    TypeSchemaBuilder.RegisterSchemaAndType

                        (“CogObjectStoreItem”, this.GetType());

                }

 

                // get a new session from the current context.

                session = Context.Repository.CreateSession();

 

                // wrap it in a transaction

                session.BeginTransaction();

 

                // make sure the id has been defined.

                if (this.Id.Equals(Guid.Empty))

                {

                    this.Id = Guid.NewGuid();

                }

 

                //persist

                session.Save(this);

                session.CommitTransaction();

            }

            catch (ElektroPostException exception)

            {

                // … rollback the transaction and do some reporting

                session.RollbackTransaction();

                throw exception;

            }

            finally

            {

                if (session != null)

                {

                    session.Close();

                }

            }

        }

 

        public static CogObjectStoreItem Load(object Id)

        {

            ISession session = null;

            try

            {

                // make sure there is a schema to read from.

                if (Context.Repository.SchemaForType(typeof(CogObjectStoreItem))==null)

                {

                    return null;

                }

 

                //acquire a session

                session = Context.Repository.CreateSession();

 

                // … and load the object

                return (CogObjectStoreItem)session.Load(Id);

            }

            catch (ElektroPostException exception)

            {

                // … do some reporting

                throw exception;

            }

            finally

            {

                if (session != null)

                {

                    session.Close();

                }

            }

        }

        public override string ToString()

        {

            return this.id.ToString();

        }

 

    }

}

The Conclusion

ObjectStore seems like a kind of Hibernate surrogate, the cool thing is that you can create the stored data without modifying the database schema, the not so cool is that there may be a serious penalty for bigger structures and I suspect there might be issues with speed for large data sets since the searching technique implemented seems to require that the objects be de-serialized to be checked if the match the filter.

Mateusz is going to test its performance over the following days to decide if it’s going to perform with what we need it for and I’ll try to see if I can get some hints for solving our problem on the EPiServer developer forums. But then again, even if it’s nto going to be our solution it may still prove useful for other issues.

1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 4.50 out of 5)
Loading...



This entry (Permalink) was posted on Friday, March 30th, 2007 at 3:15 pm and is filed under C#, EPiServer. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response , or trackback from your own site.