A day in the life...

public class GeekEarth : Earth { }
posts - 13, comments - 13, trackbacks - 0

ECO Persistence Mapper per connection

The Enterprise Core Objects Persistence Mapper is a singleton which is used by all EcoSpace instances.  It’s purpose is to load mapping information from the DB when your app starts and to cache it, improving performance.

I needed a connection per client, all running within a single application.  This was a problem because once the PMP is created its connection string is tied to a single database.  So I had to come up with a new PersistenceMapperDynamicSharer component.  It is used on the EcoSpace to specify the PMapper type; additionally you can specify a connection string to use.

It works by dynamically creating a descendant class of your PersistenceMapperProvider at runtime, one for each connection string.

 

   1:    public class PersistenceMapperDynamicSharer : PersistenceMapperSharer
   2:    {
   3:      static ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
   4:      static Dictionary<string, PersistenceMapperProvider> MapperProviders = new Dictionary<string, PersistenceMapperProvider>();
   5:   
   6:      [Browsable(false)]
   7:      public string ConnectionString { get; set; }
   8:   
   9:      public override IPersistenceMapper GetPersistenceMapper(ITypeSystemService typeSystemService)
  10:      {
  11:        return GetPersistenceMapperProvider().GetPersistenceMapper(typeSystemService);
  12:      }
  13:   
  14:      public override void ReturnPersistenceMapper(IPersistenceMapper persistenceMapper)
  15:      {
  16:        GetPersistenceMapperProvider().ReturnPersistenceMapper(persistenceMapper);
  17:      }
  18:   
  19:      PersistenceMapperProvider GetPersistenceMapperProvider()
  20:      {
  21:        //No connection string = default mapper provider
  22:        if (string.IsNullOrEmpty(ConnectionString))
  23:          return PersistenceMapperProvider.GetInstance(MapperProviderType);
  24:   
  25:        PersistenceMapperProvider result;
  26:        Locker.EnterUpgradeableReadLock();
  27:        try
  28:        {
  29:          if (MapperProviders.TryGetValue(ConnectionString, out result))
  30:            return result;
  31:          Locker.EnterWriteLock();
  32:          try
  33:          {
  34:            var mapperType = CreateNewPersistenceMapperProviderType();
  35:            result = (PersistenceMapperProvider)Activator.CreateInstance(mapperType);
  36:            ((IDynamicallySharedPersistenceMapper)result).SetConnectionString(ConnectionString);
  37:            MapperProviders[ConnectionString] = result;
  38:          }
  39:          finally
  40:          {
  41:            Locker.ExitWriteLock();
  42:          }
  43:        }
  44:        finally
  45:        {
  46:          Locker.ExitUpgradeableReadLock();
  47:        }
  48:        return result;
  49:      }
  50:   
  51:      Type CreateNewPersistenceMapperProviderType()
  52:      {
  53:        string guid = Guid.NewGuid().ToString();
  54:        var assemblyName = new AssemblyName(guid);
  55:        var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
  56:          assemblyName, 
  57:          System.Reflection.Emit.AssemblyBuilderAccess.Run);
  58:        var moduleBuilder = assemblyBuilder.DefineDynamicModule(guid);
  59:        var typeBuilder = moduleBuilder.DefineType(
  60:          guid, 
  61:          TypeAttributes.Class | TypeAttributes.Public, 
  62:          MapperProviderType);
  63:        return typeBuilder.CreateType();
  64:      }
  65:    }

 

On my EcoSpace I have a method called ActivateWithConnectionString which I can use whenever I need to activate the EcoSpace connecting to a connection string OTHER than the default…

   1:      public void ActivateWithConnectionString(string connectionString)
   2:      {
   3:        persistenceMapperDynamicSharer1.ConnectionString = connectionString;
   4:        Active = true;
   5:      }

 

And on my PersistenceMapperProvider I need to implement IDynamicallySharedPersistenceMapper like so…

   1:      void IDynamicallySharedPersistenceMapper.SetConnectionString(string connectionString)
   2:      {
   3:        sqlConnection1.ConnectionString = connectionString;
   4:      }

 

Now I can benefit from the performance gains from the singleton-pattern implemented by PersistenceMapperProvider and connect to different databases.

Print | posted on Monday, August 17, 2009 10:33 AM |

Feedback

No comments posted yet.

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 2 and 6 and type the answer here:

Powered by: