Entlib 5.0 + SqlCE 4.0 + Unity

Topics: Data Access Application Block
Oct 8, 2011 at 10:06 PM

OK, I have been working on this for several days and can't seem to resolve my problem. My intention is to ulimately use this in a wcf service, but for simplicity's sake, I am currently using a simple Console app for testing. I have the following in my Main function:

IUnityContainer container = new Unitycontainer();

var dao = container.Resolve<IMyDao>();

My config file has the unity configuration element

    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />

I have also done the following rebinding to support a private deployment of SqlCE:

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral" />
        <bindingRedirect oldVersion="" newVersion="" />

I start the range at because Entlib is compiled with SqlCe 3.5. I saw somewhere the suggestion I re-compile EntlLib with a reference to the 4.0 assembly; I did this, same result. I also put the SqlCe DbProvider into the configuration:

      <remove invariant="System.Data.SqlServerCe.4.0" />
      <add name="Microsoft SQL Server Compact Data Provider 4.0"
         description=".NET Framework Data Provider for Microsoft SQL Server Compact"
         type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />

Finally, here is the unity configuration in the config:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
      <extension type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.EnterpriseLibraryCoreExtension, Microsoft.Practices.EnterpriseLibrary.Common" />
      <register type="IMyDao, CETest" mapTo="MyDao, CETest">
          <param name="database" dependencyName="MyDb" />

 And of course, a connectionString:

  <clear />
  <add name="MyDb" providerName="System.Data.SqlServerCe.4.0" connectionString="Data Source=MyDb.sdf" />

As you can see from the unity section, MyDao has a constructor which expects a database, and I am relying on the Entlib core extension to resolve this from "MyDb". The point is, this "works", except the resolved database object is always of type GenericDatabase, not SqlCeDatabase. When I expand this in the debugger, I find that it even recognizes SqlCeDbProvider as its DbProvider, but it doesn't seem to matter, I get a GenericDatabase. I can go ahead and execute Sql against the 4.0 database, and it actually works, but of course I can't access any SqlCe specific functions, like db.ExecuteResultSet().

This is driving me nuts. As mentioned above, re-compiling EntLib against the SqlCe 4.0 doesn't seem to make a difference. Also, if I just "new up" an SqlCeDatabase with my connections string, it all works, but I'm trying to get the container to inject the same thing into MyDao. The other thing is that if I change the MyDb connection string to point to an ordinary Sql Server, I get an injected SqlDatabase, as expected.

So close, what am I missing here?



Oct 11, 2011 at 1:23 PM

Why not use EF instead?

Oct 11, 2011 at 4:17 PM
Edited Oct 11, 2011 at 4:18 PM

Acually, I thought of that, but my Corporate policy is against using ANY ORM at the present time. Yes, I know it's stupid, but I don't get to control it.

After digging into the EntLib source, I discovered that you get a GenericDatabase for anything other than SQL server or Oracle. So I would need to make changes to the EntLib source, which is also against Corporate policy. I can actually see the point of GenericDatabase for CE; it makes your code more portable, especially if you want to upgrade to real SQL Server. Anyway, I've decided for now I will just have to code to GenericDatabase and wait for some more enlightened policies at work. Actually, the first prototype I did used EF 4.0, and it worked quite nicely. Someday.

Apr 30, 2012 at 9:56 PM
Edited Apr 30, 2012 at 9:59 PM

@Dave, I think this thread addresses the issue you were having: http://entlib.codeplex.com/discussions/351542.  (I know this is old but hopefully can help you or someone else.)

The DbProviderFactories settings should be set up in machine.config.  If not then you can include them in your local config file (as you have above).  I think the one step you were missing was mapping the provider to a database so that when you requested a provider of type System.Data.SqlServerCe.4.0 a SqlCeDatabase would be returned instead of a GenericDatabase.

This configuration worked for me with out of the box Enterprise Library:

<?xml version="1.0"?>
    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true"/>
  <dataConfiguration defaultDatabase="SQLCE4">
      <add databaseType="Microsoft.Practices.EnterpriseLibrary.Data.SqlCe.SqlCeDatabase, Microsoft.Practices.EnterpriseLibrary.Data.SqlCe, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    <add name="SQLCE4" connectionString="data source=C:\Database1.sdf" providerName="System.Data.SqlServerCe.4.0"/>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral"/>
        <bindingRedirect oldVersion="" newVersion=""/>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>

Randy Levy
Enterprise Library support engineer