I am trying to use unity to automatically inject a datacontext on my repository using a new instance each time.., my idea is the ensure that each time a new datacontext is injected
Currently its failing on creating the repository, i think it can't resolve MyDataContext
Before creating a constructor on "the repository" (see below) to take in the DataContext on my repository everything worked but now its failing..
I currently have this setup in my unity container which i create in global.asax, i have also registered the type MyDataContext which is standard DataContext
container = new UnityContainer();
Container.RegisterType<MyDataContext, MyDataContext>()
.RegisterType<IOfficeRepository, OfficeRepository>()
.RegisterType<IOfficeService, OfficeService>();
basically i have a service that calls the repository like so
public class OfficeService : IOfficeService
{
IOfficeRepository repository = null;
public OfficeService(IOfficeRepository repository)
{
this.repository = repository;
if (this.repository == null)
throw new InvalidOperationException("Repository cannot be null");
}
here is my repository
public class OfficeRepository : IOfficeRepository
{
private MyDataContext db;
public OfficeRepository (MyDataContext dataContext)
{
this.db = dataContext;
}
EDIT
I almost forgot i am doing this to create the service
officeService = Bootstrapper.Container.Resolve<IOfficeService>();
EDIT - THE ERROR BEING GENERATED
Resolution of the dependency failed, type = "MarkSmith.IOfficeService", name = "".
Exception message is: The current build operation (build key Build
Key[MarkSmith.OfficeService, null]) failed: The parameter repository could not be
resolved when attempting to call constructor
MarkSmith.OfficeService(MarkSmith.IOfficeRepository repository). (Strategy type BuildPlanStrategy, index 3)
EDIT - REMOVING Constructor on repository works
It is something to do with the datacontext because if i remove the constrcutor on the repository that takes a DataContext then all works, but of course i need it to accept a DataContext to be able to inject a "NEW" datacontext each time
public class OfficeRepository : IOfficeRepository
{
private MyDataContext db new MyDataContext(); // CHANGE
//public OfficeRepository (MyDataContext dataContext)
//{
//this.db = dataContext;
//}
EDIT - ACTUAL ERROR
After digging deeper i have found this error ....
The type MyDataContext has multiple constructors of length 2.
Unable to disambiguate. (Strategy type DynamicMethodConstructorStrategy, index 0)
(Strategy type BuildPlanStrategy, index 3)
EDIT - TEST TO RESOLVE THE DATACONTEXT with 1 line of code
This also fails with the same error as above - multiple constructors
MyDataContext test = Bootstrapper.Container.Resolve<MyDataContext >();
EDIT - ALL CONSTRUCTORS ON MY DATACONTEXT
These were created by an exernal util but all should be well..
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext()
: base(ConnectionString, mappingCache)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(string connection)
: base(connection, mappingCache)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(System.Data.IDbConnection connection)
: base(connection, mappingCache)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource)
: base(connection, mappingSource)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource)
: base(connection, mappingSource)
{
OnCreated();
}
EDIT - To demonstrate creating the DataContext in code without Unity works 100% without issue
MyDataContext tes2t = new MyDataContext ();
I'm not sure this works, but have you tried to register MyDataContext as a component rather than a type mapping?
container.RegisterType<MyDataContext>();
instead of
container.RegisterType<MyDataContext, MyDataContext>();
EDIT based on new information
The culprit seems to be that MyDataContext has more than one constructor. This is a common issue with most DI Containers, because they need to pick and use only one. If you can remove the ambiguity by constraining MyDataContext to have only one constructor, that will probably be the simplest solution.
Otherwise, you should be able to use an InjectionConstructor instance to identify the constructor when you register the repository. Let's assume you want to use a constructor that takes a connection string as an argument:
string connectionString =
ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
var injectedConnectionString = new InjectionConstructor(connectionString);
container.RegisterType<MyDataContext>(injectedConnectionString);
With multiple constructors to choose from, Unity doesn't know which one to use. It will choose the one with the most arguments that can all be satisfied, but in this case there are two constructors each with two resolvable arguments.
If you don't want to couple your MyDataContext
class to Unity and use the InjectionConstructor
attribute as suggested by Scott (upvoted :)), you can specify the constructor that should be used at the time of registration using the fluent interface. See Configuring Constructor, Property, and Method Injection for details.
I don't see your MyDataContext constructors; but try to add the [InjectionConstructor] attribute to the one you want to use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With