How to configure KiGG to use Entity Framework Repository

Introduction

KiGG Entity Framework based repositories currently support 2 database engines out of the box, SQL Server 2005/2008 including express editions and MySQL 5.1. However it is possible to support any other database engine like SQLite, VistaDB, Oracle etc... as long as there is a .Net Data Provider that is support Entity Framework for the desired database.

Configuring connection string for KiGG database

Find connectionStrings element and add your connection string as the following:
<connectionStrings>
   <clear/>
   <add 
      name="KiGGDatabaseConnectionStringName"
      connectionString="Data Source=.\SQLEXPRESS;Database=KiGG;user Id=YourUserName,password=YourPassword"
      providerName="System.Data.SqlClient"/>
 </connectionStrings>
NOTE: The above defined connection string is on SQL Server 2005/2008 Express Edition instance with mixed authentication using database user and password.

About KiGG design and repository providers

KiGG based on totally decoupled components using IoC/DI (Inversion of Control through Dependecy Injection). The default configuration of KiGG is targetting LINQ to SQL as repository provider. However you can easly change this configuration to target any other KiGG repository provider you wish to use. Here I'm going to show how to configure KiGG to user Entity Framework repository provider.

What is KiGG repository provider

The term Repository Provider is my own invention, so don't take it as standard term, I use it here just to simplify the idea.
KiGG Repository is set of interfaces that defines how KiGG should interact and query the underlaying data storage to return KiGG domain object models such as Story model. These interfaces can be implemented using whatever you want. Currently we provide 2 implementations one based on LINQ to SQL and the other one is based on Entity Framework. I call each implementation a KiGG Repository Provider, and so we are going now to configure KiGG to use Entity Framework repository provider.

About KiGG Entity Data Model (EDM) files (CSDL, SSDL & MSL)

Entity Framework data model files (CSDL, SSDL, & MSL) should be placed under App_Data directory. Although it is possible to configure the path of these files, it is highly recommended to place them under this directory for protection. Files are:
  1. DomainObjects.csdl (This file should be readonly and never be modified)
  2. DomainObjects.msl (this file should be readonly and never be modified)
  3. DomainObjects.ssdl (default SSDL that tagets SQL Server .Net Data Provider)
  4. DomainObjects.SqlServer.ssdl (SSDL that tagets SQL Server .Net Data Provider)
  5. DomainObjects.MySql.ssdl (SSDL that tagets MySQL .Net Data Provider "Connector\net" )
KiGG dosen't support single EDM file that is normally generated by Visual Studio in order to be able to modify SSDL separately per .Net Data Provider.

NOTE: SSDL file is modified per .Net Data Provider to basically specify the provider & define proper supported storage data types which might be different between storage engines.

Mapping KiGG domain objects & repository interfaces to KiGG Entity Framework provider specific types

First step is to modify Web.config to configure Domain Objects & Repository interfaces by mapping them to desired repository provider.

Registring Entity Framework repository types

Open your Web.config. Under unity configuration section (<unity> Element) add type aliases to Entity Framework Repository concrete types as the following:
<unity>
	<typeAliases>
		....
		<typeAlias alias="IEFConnectionString" 
			type="Kigg.EF.Repository.IConnectionString, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFConnectionString" 
			type="Kigg.EF.Repository.ConnectionString, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFDomainObjectFactory" 
			type="Kigg.EF.DomainObjects.DomainObjectFactory, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFDatabaseFactory" 
			type="Kigg.EF.Repository.DatabaseFactory, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFUnitOfWork" 
			type="Kigg.EF.Repository.UnitOfWork, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFUserRepository" 
			type="Kigg.EF.Repository.UserRepository, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFCategoryRepository" 
			type="Kigg.EF.Repository.CategoryRepository, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFTagRepository" 
			type="Kigg.EF.Repository.TagRepository, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFStoryRepository" 
			type="Kigg.EF.Repository.StoryRepository, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFKnownSourceRepository" 
			type="Kigg.EF.Repository.KnownSourceRepository, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFCommentRepository"
			type="Kigg.EF.Repository.CommentRepository, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFCommentSubscribtionRepository" 
			type="Kigg.EF.Repository.CommentSubscribtionRepository, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFMarkAsSpamRepository" 
			type="Kigg.EF.Repository.MarkAsSpamRepository, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFStoryViewRepository" 
			type="Kigg.EF.Repository.StoryViewRepository, Kigg.Infrastructure.EF"/>
		<typeAlias alias="EFVoteRepository" 
			type="Kigg.EF.Repository.VoteRepository, Kigg.Infrastructure.EF"/>
	</typeAliases>
	<containers>
		<container>
                      ......
                </container>
	</containers>
</unity>

NOTE: You might notice that LINQ to SQL type aliases are already defined. Don't worry, you can keep them because our aliases are different.

Mapping KiGG repository interfaces to registered Entity Framework repository provider

Also under unity configuration section (<unity> Element) there is subelement <containers> where default container is defined (<container> element). Under default container (<container> element with no name attribute) we need to update the mappings of KiGG repository interfaces. Default configuration maps to LINQ to SQL types, we need to change these mappings to map to Entity Framwork repository types as the following:
  • Find mapping for IDomainObjectFactory interface and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
	  <type type="IDomainObjectFactory" mapTo="EFDomainObjectFactory">
	    <lifetime type="Singleton"/>
	  </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
NOTE: mapTo attribute maps to EFDomainObjectFactory which is one of the typeAliases we just added in Registring Entity Framework repository types.
We will do the same with the rest of repository interfaces.
  • Add mapping for IConnectionString -Which is IEFConnectionString in typeAliases defined above- interface and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
	 <type type="IEFConnectionString" mapTo="EFConnectionString">
            <lifetime type="Singleton"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="configuration" parameterType="IConfigurationManager">
                  <dependency/>
                </param>
                <param name="name" parameterType="System.String">
                  <value type="System.String" value="KiGGDatabaseConnectionStringName"/>
                </param>
                <param name="edmFilesPath" parameterType="System.String">
                  <value type="System.String" value="|DataDirectory|"/>
                </param>
                <param name="ssdlFileName" parameterType="System.String">
                  <value type="System.String" value="DomainObjects.SqlServer"/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
NOTE: In the above configuration for IConnectionString that maps to EFConnectionString Entity Framework repository type I wish to highlight the injected constructor parameters.
  1. Parameter configuration is as it is, it maps to a configured IConfigurationManager that already maps to a concrete class that is independent from Entity Framework.
  2. Parameter name, the value of this parameter is your database connection string name that you'll configure under connectionStrings element.
  3. Paremeter edmFilesPath, this is the physical path of csdl,ssdl and msl files path. By default all these files are under App_Data directory so the default value is "|Directory|"
  4. Parameter ssdlFileName, this is the name of the SSDL file without extension. Because SSDL might be specific per .Net Data Provider then we had to define this as configurable parameter. The default value maps to SqlServer specific SSDL. Read this article for MySql configuration.
  • Find mapping for IDatabaseFactory interface and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
	  <type type="IDatabaseFactory" mapTo="EFDatabaseFactory">
            <lifetime type="PerWebRequest"/>
            <typeConfig
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="connectionString" parameterType="IEFConnectionString">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
          <type name="Async" type="IDatabaseFactory" mapTo="EFDatabaseFactory">
            <lifetime type="Singleton"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="connectionString" parameterType="IEFConnectionString">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
Note: There are 2 mappings above, default one has no name and the other is has Async as a name, both are for IDatabaseFactory and must be changed.
  • Find mapping for IUnitOfWork interface and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
	  <type type="IUnitOfWork" mapTo="EFUnitOfWork">
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
          <type name="Async" type="IUnitOfWork" mapTo="EFUnitOfWork">
            <lifetime type="Singleton"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency name="Async"/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
  • Add the following type mappings -Note that they all have name set to "EntityFramework"-:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
	  <type name="EntityFramework" type="IUserRepository" mapTo="UserRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
          <type name="EntityFramework" type="ICategoryRepository" mapTo="EFCategoryRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
          <type name="EntityFramework" type="ITagRepository" mapTo="EFTagRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
          <type name="EntityFramework" type="IStoryRepository" mapTo="EFStoryRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
  • Find mapping for IUserRepository, ICategoryRepository, ITagRepository & IStoryRepository with name="Logging" and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
          <type name="Logging" type="IUserRepository" mapTo="LoggingUserRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="innerRepository" parameterType="IUserRepository">
                  <dependency name="EntityFramework"/>
                </param>
              </constructor>
            </typeConfig>
          </type>
          <type name="Logging" type="ICategoryRepository" mapTo="LoggingCategoryRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="innerRepository" parameterType="ICategoryRepository">
                  <dependency name="EntityFramework"/>
                </param>
              </constructor>
            </typeConfig>
          </type>
          <type name="Logging" type="ITagRepository" mapTo="LoggingTagRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="innerRepository" parameterType="ITagRepository">
                  <dependency name="EntityFramework"/>
                </param>
              </constructor>
            </typeConfig>
          </type>
          <type name="Logging" type="IStoryRepository" mapTo="LoggingStoryRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="innerRepository" parameterType="IStoryRepository">
                  <dependency name="EntityFramework"/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
Note: The Contructor parameter innerRepository in all mappings above has a dependency on EntityFramework type defined in previous step. The <dependency> element instructs the constructor to use the defined EntityFramework type by specifying name attribute of <dependency> element.
  • Find mapping for IKnownSourceRepository and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
          <type type="IKnownSourceRepository" mapTo="EFKnownSourceRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
  • Find mapping for ICommentRepository and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
          <type type="ICommentRepository" mapTo="EFCommentRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
  • Find mapping for ICommentSubscribtionRepository and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
          <type type="ICommentSubscribtionRepository" mapTo="EFCommentSubscribtionRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
  • Find mapping for IMarkAsSpamRepository and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
          <type type="IMarkAsSpamRepository" mapTo="EFMarkAsSpamRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
  • Find mapping for IStoryViewRepository and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
          <type type="IStoryViewRepository" mapTo="EFStoryViewRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>
  • Find mapping for IVoteRepository and change it:
<unity>
    <typeAliases>
	....
    </typeAliases>
    <containers>
      <container>
        <types>
	  ....
          <type type="IVoteRepository" mapTo="EFVoteRepository">
            <lifetime type="PerWebRequest"/>
            <typeConfig 
            extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="factory" parameterType="IDatabaseFactory">
                  <dependency/>
                </param>
              </constructor>
            </typeConfig>
          </type>
	  ....
	</types>		
     </container>
    </containers>
</unity>

Configuring KiGG to use MySQL

To configure KiGG to use MySQL read this article

Last edited Sep 13, 2009 at 12:14 AM by mosessaur, version 9

Comments

ZeroInfinity Oct 16, 2009 at 9:10 AM 
DomainObjects.csdl (This file should be readonly and never be modified)
DomainObjects.msl (this file should be readonly and never be modified)
DomainObjects.ssdl (default SSDL that tagets SQL Server .Net Data Provider)
DomainObjects.SqlServer.ssdl (SSDL that tagets SQL Server .Net Data Provider)
DomainObjects.MySql.ssdl (SSDL that tagets MySQL .Net Data Provider "Connector\net" )

Which ones I need If I am using the SQL Server and if I make a change to the database, how I can generate these files and what is the name of the Entity name for the EF to generate. Which name are you using? If you can explain the process that would be great.
Thank you so much.