please help with unity+dbcontext

Jun 28, 2012 at 2:42 PM

my config file like this:

<alias alias="DbContext" type="System.Data.Entity.DbContext,EntityFramework"/>

<register type="DbContext" mapTo="DbContext" name="dbContext">
        <constructor>
          <param name="nameOrConnectionString" value="pianoEntities"></param>
        </constructor>
 </register>

when I tested it throw exception:

System.InvalidOperationException: The type name or alias DbContext could not be resolved. Please check your configuration file and verify this type name.

the Dbcontext is entityframe's.

namespace System.Data.Entity
{
        public class DbContext : IDisposable, IObjectContextAdapter

……

}

in EntityFramework.dll

how to do?

thanks!

Jun 29, 2012 at 6:30 AM

the problem I have resolved,but no DbContext have many constructor and I can't modify it's code to set injection constructor.

how to set it in xml?

<register type="DbContext" mapTo="DbContext" name="dbContext">
        <constructor>
          <param name="nameOrConnectionString" type="System.String" value="pianoEntities"></param>
        </constructor>
      </register>

My xml like this when unity resolve it , call the constructor is 

public DbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection)

I want to call

public DbContext(string nameOrConnectionString)

Jun 29, 2012 at 10:04 AM

How you have registered DbContext is the way to indicate what constructor to use.  However, because Unity is resolving the most complex constructor for DbContext it looks like Unity is not using that configuration to resolve DbContext.  The reason is probably that the registration in the configuration is using a name ("dbContext").  Are you sure that you are resolving by name (you may have to use the dependencyName configuration value if that is your intent).

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jun 29, 2012 at 2:38 PM
Edited Jun 29, 2012 at 2:42 PM

my xml like this:

<alias alias="IGenericRepository" type="ettaingroup.data.ef.Interfaces.IGenericRepository`1,ettaingroup.data.ef"/>
    <alias alias="Repository" type="ettaingroup.data.ef.Repositories.Repository`1,ettaingroup.data.ef"/>
    <alias alias="UnitOfWork" type="ettaingroup.data.ef.UnitOfWork,ettaingroup.data.ef"/>
    <alias alias="DbContext" type="System.Data.Entity.DbContext,EntityFramework"/>

 

<container name="pianoContainer">
      <register type="DbContext" mapTo="DbContext" name="dbContext">
        <constructor>
          <param name="nameOrConnectionString" type="System.String" value="pianoEntities"></param>
        </constructor>
      </register>
      <register type ="IGenericRepository" mapTo="Repository" name="pianoRepository">
        <constructor>
          <param name="context">
            <dependency name="dbContext"/>
          </param>
        </constructor>
      </register>
      <register type="UnitOfWork" mapTo="UnitOfWork" name="unitOfWork">
        <constructor>
          <param name="ctx">
            <dependency name="dbContext"/>
          </param>
        </constructor>
      </register>

     <register type="ISysDepartmentService" mapTo="SysDepartmentService" name="sysDepartmentService">
        <constructor>
          <param name="sysDepartmentDal">
            <dependency name="pianoRepository"></dependency>
          </param>
          <param name="unitOfWork">
            <dependency name="unitOfWork"></dependency>
          </param>
        </constructor>
      </register>

……

</container>

 

if repository and unitofwork config constructor without param ,unity can work good!

Jun 29, 2012 at 3:47 PM
Edited Jun 29, 2012 at 3:48 PM

How is ISysDepartmentService resolved?  When you resolve ISysDepartmentService are you resolving by name?  There is no default registration, the only registration provided is for a named registration ("sysDepartmentService") so you would need to resolve using the name (e.g. container.Resolve<ISysDepartmentService>("sysDepartmentService") ) in order to use the dependencies specified in the configuration file.  Otherwise Unity will just use the default plan which will attempt to construct dependencies using the most complicated constructor approach.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jun 30, 2012 at 12:59 AM

In my common file resolve the service like this:

public static T GetServiceInstance<T>(string name)
        {
            IUnityContainer myContainer = new UnityContainer();
            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            section.Configure(myContainer, "pianoContainer");
            T myServiceInstance = myContainer.Resolve<T>(name);
            return myServiceInstance;
        }

when I want to use one service I call :

ISysDepartmentService myServiceInstance = Common.GetServiceInstance<ISysDepartmentService>("sysDepartmentService");

SysDepartmentService only constructor:

private Repository<SysDepartment> _sysDepartmentDal;
        private UnitOfWork _unitOfWork;

        public SysDepartmentService(Repository<SysDepartment> sysDepartmentDal,UnitOfWork unitOfWork)
        {
            _sysDepartmentDal = sysDepartmentDal;
            _unitOfWork = unitOfWork;
        }

thanks!

Jun 30, 2012 at 6:32 AM

Based on the code snippets, everything seems to work fine on my side.  Can you provide a small project that recreates the issue?

On an unrelated note, just curious why a new UnityContainer is created for every call to GetServiceInstance?  It would be more efficient to load the container and keep a reference to it (e.g. Singleton) for future resolves.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jun 30, 2012 at 1:24 PM

I have tried to use unity few days,first I want to auto construct object use ioc.

So I not understand the note,how to use singleton?You mean is when I want to resolve service do not create unitycontainer every times?

Jun 30, 2012 at 2:42 PM

If I can change UnityContainer to static in my common file?like this:

private static IUnityContainer myContainer;

public static T GetServiceInstance<T>(string name)
        {
            T myServiceInstance = myContainer.Resolve<T>(name);
            return myServiceInstance;
        }

when the application run first create the unitycontainer,and if i want to resolve object use:

Common.GetServiceInstance<T>(TName); is ok?

when i test always throw exception when resolved DbContext:

Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, type = "PianoBusiness.SysManager.ISysDepartmentService", name = "sysDepartmentService".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type DbConnection cannot be constructed. You must configure the container to supply this value.

Resolving PianoBusiness.SysManager.Impl.SysDepartmentService,sysDepartmentService (mapped from PianoBusiness.SysManager.ISysDepartmentService, sysDepartmentService)
  Resolving parameter "sysDepartmentDal" of constructor PianoBusiness.SysManager.Impl.SysDepartmentService(ettaingroup.data.ef.Repositories.Repository`1[[PianoData.SysDepartment, PianoData, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] sysDepartmentDal, ettaingroup.data.ef.UnitOfWork unitOfWork)
    Resolving ettaingroup.data.ef.Repositories.Repository`1[PianoData.SysDepartment],pianoRepository
    Resolving parameter "context" of constructor ettaingroup.data.ef.Repositories.Repository`1[[PianoData.SysDepartment, PianoData, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]](System.Data.Entity.DbContext context)
      Resolving System.Data.Entity.DbContext,dbContext
      Resolving parameter "existingConnection" of constructor System.Data.Entity.DbContext(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, System.Boolean contextOwnsConnection)
        Resolving System.Data.Common.DbConnection,(none)

I can't resolve DbContext because DbContext have a constructor with three params.I want to call constructor is "public DbContext(string nameOrConnectionString)",but can't set "InjectionConstructor" !

how to do?

Jul 3, 2012 at 4:31 AM

As I said, my sample code based on your code snippets is working OK.  It's difficult to piece together what is going on from the various code snippets; if you could post a sample application that recreates the issue it would be helpful.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jul 3, 2012 at 9:21 AM

when I wrote a sample application which I want to sending you,It work ok.only I update my ef.dll from 4.1 to 4.3.

thanks!

ps:I want to know if I register like this,Is unitofwork and repository have a same object instance type of dbcontext?

Jul 4, 2012 at 4:25 AM
Edited Jul 4, 2012 at 3:32 PM

Good to hear it seems to be sorted out.  

Based on what I see above each resolve of DbContext would be a new instance.  If you want to resolve the same instance for all calls in your application then you should register DbContext with the lifetime set to singleton:

 

      <register type="DbContext" mapTo="DbContext" name="dbContext">
        <lifetime type="singleton"/>
        <constructor>
          <param name="nameOrConnectionString" type="System.String" value="pianoEntities"></param>
        </constructor>
      </register>

 

If you ware looking for the same DbContext per HttpContext then you could look at http://unity.codeplex.com/discussions/242485 or http://unitymvc3.codeplex.com

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jul 4, 2012 at 1:55 PM

thank you very much!

when I set lifetime,repositories and unitofwork have the same dbcontext instance and resolved any problems!

 

thanks!