valdis
Oct 4, 2011
  6840
(2 votes)

If all you need is just Dynamic Data Store..

We had recently task to make a module data store agnostic. This means that it shouldn’t be a problem to switch from Dynamic Data Store to some other storage implementation. Back and forth. No big deal.

As we currently are developing in our sandbox and making some prototypes only, idea was to bring DDS in our sandbox. We didn’t wanted to deal with all that complexity of EPiServer for now just to be able to use DDS for out testing purposes.

Things to happen, first we need to bring in section from web.config file.

 

<section name="episerver.dataStore" type="EPiServer.Data.Configuration.EPiServerDataStoreSection, EPiServer.Data"/>

 

And then we need to copy section and its content as well (for testing purposes we disabled caching):

 

<episerver.dataStore>
      <dataStore defaultProvider="EPiServerSQLServerDataStoreProvider">
        <providers>
          <add name="EPiServerSQLServerDataStoreProvider" description="SQL Server implementation of Data Store" type="EPiServer.Data.Dynamic.Providers.SqlServerDataStoreProvider, EPiServer.Data" connectionStringName="EPiServerDB"/>
        </providers>
        <cache defaultProvider="nullCacheProvider">
          <providers>
            <add name="httpCacheProvider" description="Http Cache implementation for DataStore" type="EPiServer.Data.Cache.HttpRuntimeCacheProvider,EPiServer.Data.Cache"/>
            <add name="nullCacheProvider" description="Null Cache implementation for DataStore" type="EPiServer.Data.Cache.NullCacheProvider,EPiServer.Data"/>
          </providers>
        </cache>
      </dataStore>
    </episerver.dataStore>

 

Remember to add connection string in <connectionStrings> section as well.

 

connectionStringName="EPiServerDB"

 

That’s almost it.

We would need to reference EPiServer.CMS.Core and EPiServer.Framework NuGet packages to get EPiServer.Data.Dynamic namespace in codebase.

 

Next thing is to initialize store to get a working copy. After sniffing around EPiServer source code we found that particular initialization module is doing required stuff.

 

EPiServer.Web.InitializationModule._initializationEngine.Add((System.Action) (() => EPiServer.Web.InitializationModule.InitializeDynamicDataStore()), new System.Action(EPiServer.Web.InitializationModule.UninitializeDynamicDataStore));

 

And particularly this method:

 

private static void InitializeDynamicDataStore()
{
  ...
    DynamicDataStoreFactory.Instance = (DynamicDataStoreFactory) new EPiServerDynamicDataStoreFactory();

  ...
}

 

And looking at TypeExtensions that provide convenient way to get store instance:

 

public static DynamicDataStore GetOrCreateStore(this Type type)
{
  return DynamicDataStoreFactory.Instance.GetStore(type) ?? DynamicDataStoreFactory.Instance.CreateStore(type);
}

 

We found a way if we set store instance property to EPiServerDynamicDataStoreFactory. instance – everything works correctly and you are ready to go with DDS support in your very disconnected from the EPiServer sandbox project.

But to make it more easier for testing, imagine that it would classical requirement to be able to mock store and test against some simpler or even mocked instance of the DynamicDataStore type. We adjusted our data store facade to be able to accept various kinds of factories which would make instances of data store as required.

 

private readonly DynamicDataStoreFactory storeFactory;

public OurEPiServerStore()
{
    if(DynamicDataStoreFactory.Instance == null)
    {
        this.storeFactory = DynamicDataStoreFactory.Instance = new EPiServerDynamicDataStoreFactory();
    }

    this.storeFactory = DynamicDataStoreFactory.Instance;
}

public OurEPiServerStore(DynamicDataStoreFactory factory)
{
    this.storeFactory = factory;
}

 

And then it’s just more easier to unit test our store behaviour and surrounding environment with something like this:

var factoryMock = new Mock<DynamicDataStoreFactory>();
var storeMock = new Mock<DynamicDataStore>();

factoryMock.Setup(f => f.GetStore(typeof(EmailModel))).Returns(storeMock.Object);

var store = new NewsletterStore<ModelType>(factoryMock.Object);

 

That’s it! Hope this helps.

Oct 04, 2011

Comments

joel.williams@auros.co.uk
joel.williams@auros.co.uk Jun 27, 2013 01:00 AM

Hi Valdis,

Thanks for putting together this article. I'm trying to replicate what you have achieved but keep getting an "StructureMap Exception Code: 202
No Default Instance defined for PluginFamily EPiServer.Data.IDatabaseHandler" exception message. Was this something that you experienced? Have I missed something from my configuration perhaps?

Thanks

Joel

valdis
valdis Jun 27, 2013 01:12 PM

This was used in CMS6. I'll check what's the case in v7. StructureMap needs to be initialized beforehand using any base classes as most of the interfaces are retrieved via ServiceLocator.

valdis
valdis Jun 27, 2013 04:03 PM

Try this code:

var container = new Container();
var factory = new SqlDatabaseFactory();
container.Configure(ce => ce.For().Use(factory.CreateDefaultHandler));
ServiceLocator.SetLocator(new StructureMapServiceLocator(container));
DataInitialization.InitializeFromCode(container, factory, null);
var store = typeof(SampleModel).GetStore();

NB! element for v7 is optional. If you still add it - be sure to clear providers list before adding - otherwise you will get "Key has already been added" type of exception.

Chirag Sharma
Chirag Sharma Nov 13, 2013 11:46 AM

Hi Valdis,

I am try to use DDS in console application for EPiServer CMS 7, I used above code for initialization .

In my App.config.












The exception I am getting is:

exception Message:
Activation error occurred while trying to get instance of type IDatabaseHandler, key ""

InnerException :

{"StructureMap Exception Code: 207\nInternal exception while creating Instance 'c83caeb3-0d4f-4775-853b-8b7ae906265a' of PluginType EPiServer.Data.IDatabaseHandler, EPiServer.Data, Version=7.0.859.24, Culture=neutral, PublicKeyToken=8fe83dea738b45b7}

StackTrace:

at StructureMap.Pipeline.LambdaInstance`1.InstanceBuild(Type pluginType, BuildSession session)
at StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session)
at StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session)
at StructureMap.Pipeline.ObjectBuilder.ConstructNew(Type pluginType, Instance instance, BuildSession session)
at StructureMap.Pipeline.ObjectBuilder.Resolve(Type pluginType, Instance instance, BuildSession session)
at StructureMap.BuildSession.CreateInstance(Type pluginType, Instance instance)
at StructureMap.BuildSession.CreateInstance(Type pluginType)
at StructureMap.Container.GetInstance(Type pluginType)
at EPiServer.ServiceLocation.StructureMapServiceLocator.DoGetInstance(Type serviceType, String key)
at EPiServer.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
at EPiServer.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService]()
at EPiServer.Data.Providers.SqlDatabaseFactory.get_CurrentHandler()
at EPiServer.Data.DataInitialization.InitializeFromCode(IContainer container, IDatabaseFactory dbHandlerFactory, CacheProvider cacheProvider)

Also where I have to set connection string name?

Thanks,
Chirag

valdis
valdis Jan 23, 2014 08:43 AM

Chirag, sorry for delayed answer. We just came across the same issue. Just check exception's inner exception. If it's complaining about "Entry point is not found", double check your app.config file. You may missing redirect to proper structuremap assembly used in project.





Emanuel Medina Gómez
Emanuel Medina Gómez Jun 21, 2017 11:59 PM

Emanuel Medina Gómez
Emanuel Medina Gómez Jun 21, 2017 11:59 PM

Please login to comment.
Latest blogs
The 1001st Piece in your 1000 Piece Puzzle: .NET Default Interface Functions

I was recently working with a client who wanted a reasonably large subsystem added to Optimizely that would add automated management to their...

Greg J | Nov 28, 2022 | Syndicated blog

Video Demonstration, creating a CMS12 Alloy Sample Site

Hey All Below you will find a quick video demonstration on how to install a local version of Alloy Sample based on CMS12 / .Net 6. As you will see ...

Minesh Shah (Netcel) | Nov 28, 2022

How to create an admin user I Optimizely CMS – with Episerver CLI

In this blog post I’ll show how to create an admin user for Optimizely CMS in a new environment where you don’t have access to the admin interface.

Ove Lartelius | Nov 28, 2022 | Syndicated blog

Optimizely shortcuts in CMS 12 will get a trailing slash appended!

Not all URLs will work when the trailing slash is added, and that could cause problems. Hopefully it will be fixed soon.

Tomas Hensrud Gulla | Nov 26, 2022 | Syndicated blog

One week left of the beta certification period

Today it's one week until the last beta certification day. Do you exam no later than Wednesday the 30th.  Here are the reference and exam guides:...

Karen McDougall | Nov 23, 2022

Unbelievable FREE Heatmapping With Optimizely Web

Within this guide, you will learn how to integrate a free heat mapping tool to Optimizely Web so you can turbocharge your A/B testing capabilities....

Jon Jones | Nov 22, 2022 | Syndicated blog