I am working on an ASP.NET WebAPI using OWIN. To manage the instances of DBContext (Entity Framework), I try to use Ninject. However, when I call a controller, the programm returns an error:
The controller cannot be created, missing constructor.
Could you tell me what is going wrong here?
My Controller Class:
public class Testcontroller
{
private IApplicationDbContext _context;
public Testcontroller(IApplicationDbContext context)
{
_context = context;
}
}
This is the Ninject-File:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<IApplicationDbContext>().To<ApplicationDbContext>();
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static void RegisterServices(IKernel kernel)
{
}
}
Ninject Dependency Scope:
public class NinjectDependencyScope : IDependencyScope
{
IResolutionRoot resolver;
public NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.TryGet(serviceType);
}
public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.GetAll(serviceType);
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
}
// This class is the resolver, but it is also the global scope
// so we derive from NinjectScope.
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
IKernel kernel;
public NinjectDependencyResolver(IKernel kernel) : base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
The Entity Framework DbContext-Class:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
}
public virtual DbSet<Models.Team> Teams { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
public interface IApplicationDbContext
{
DbSet<Models.Team> Teams { get; set; }
int SaveChanges();
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
I tried to follow this tutorial: http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api
What have I done wrong here?
Thanks in advance!
Unless there was a serious omission in you controller code, your controller is not inheriting from ApiController, as is expected with Web Api
public class TestController : ApiController {
private IApplicationDbContext _context;
public Testcontroller(IApplicationDbContext context) {
_context = context;
}
}
UPDATE
I tried to set up everything from scratch using this: http://www.alexzaitzev.pro/2014/11/webapi2-owin-and-ninject.html
For some reason, it now works out perfectly fine.
Thank you for your support!
Related
I am trying to set up UoW with Unity DI using .NET Framework, and everything works until I call the context.SaveChanges(), the ChangeTracker.HasChanges() in the context passed to the UoW shows false, so context changes are not persisting through to the UoW implementation. I have a feeling this is due to my registration of the UoW in the Unity container, as this is my first time setting this up. Does anything stand out as incorrect?
EDIT - I went around the UoW functionality and attempted to just call _context.SaveChanges() directly on my context and it still does not save. So it seems it's something beyond the UoW.
UnityConfig
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<AccountController>(new InjectionConstructor());
container.RegisterType<IChildFamilyCareProviderLinkRepository, ChildFamilyCareProviderLinkRepository>();
container.RegisterType<IFamilyCareProviderRepository, FamilyCareProviderRepository>();
container.RegisterType<IFamilyCareProviderContactRepository, FamilyCareProviderContactRepository>();
container.RegisterType<IUnitOfWork, UnitOfWork>();
container.RegisterInstance(AutoMapperConfig.Mapper);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
UnitOfWork
public class UnitOfWork : IUnitOfWork
{
private readonly RAINContext _context;
public IFamilyCareProviderRepository FamilyCareProviders { get; private set; }
public IFamilyCareProviderContactRepository FamilyCareProviderContacts { get; private set; }
public IChildFamilyCareProviderLinkRepository ChildFamilyCareProviderLinks { get; private set; }
public UnitOfWork(RAINContext context,
IFamilyCareProviderRepository familyCareProviderRepository,
IFamilyCareProviderContactRepository familyCareProviderContactRepository,
IChildFamilyCareProviderLinkRepository childFamilyCareProviderLinkRepository)
{
this._context = context;
this.FamilyCareProviders = familyCareProviderRepository;
this.FamilyCareProviderContacts = familyCareProviderContactRepository;
this.ChildFamilyCareProviderLinks = childFamilyCareProviderLinkRepository;
}
public bool Save()
{
_context.ChangeTracker.HasChanges(); //THIS SHOWS FALSE
var success = _context.SaveChanges(); //No changes are saved to DB
return success > 0;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool dispose)
{
if (dispose)
{
_context.Dispose();
}
}
}
IUnitOfWork
public interface IUnitOfWork : IDisposable
{
IFamilyCareProviderRepository FamilyCareProviders { get; }
IFamilyCareProviderContactRepository FamilyCareProviderContacts { get; }
IChildFamilyCareProviderLinkRepository ChildFamilyCareProviderLinks { get; }
bool Save();
}
Controller
public class FamilyCareProviderController : Controller
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public FamilyCareProviderController(
IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
this._mapper = AutoMapperConfig.Mapper;
}
[HttpPost]
public ActionResult CreateFamilyCareProvider(CreateFamilyCareProvider vm)
{
try
{
var fcp = new FamilyCareProvider()
{
Id = Guid.NewGuid().ToString().ToUpper(),
FamilyCareProviderName = vm.FamilyCareProviderName,
IsActive = true,
CreatedById = UserId,
LastUpdatedById = UserId
};
_unitOfWork.FamilyCareProviders.Insert(fcp);
var fcpc = _mapper.Map<FamilyCareProviderContact>(vm.FamilyCareProviderContact);
_unitOfWork.FamilyCareProviderContacts.Insert(fcpc);
var result = _unitOfWork.Save();
return RedirectToAction(nameof(Index));
}
catch (Exception)
{
ModelState.AddModelError("", "Error saving family care provider contact.");
return View(vm);
}
}
}
Is there something that is obvious that stands out in the implementation of this?
How do I update this code below to allow for multiple DbContexts? I searched other posts and I tried to make my unit of work and dbfactory classes accept a generic type but I had trouble with the RepositoryBase class, the repository, the service and tying it all together; I still struggle with generics in C#. Can anyone help me out?
DbFactory.cs
public class DbFactory : Disposable, IDbFactory
{
WilMpeContext _dbContext;
public WilMpeContext Init()
{
return _dbContext ?? (_dbContext = new WilMpeContext());
}
protected override void DisposeCore()
{
_dbContext?.Dispose();
}
}
Disposable.cs
public class Disposable : IDisposable
{
private bool isDisposed;
~Disposable()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!isDisposed && disposing)
{
DisposeCore();
}
isDisposed = true;
}
// Ovveride this to dispose custom objects
protected virtual void DisposeCore()
{
}
}
iDbFactory.cs
public interface IDbFactory : IDisposable
{
WilMpeContext Init();
}
IRepository.cs
public interface IRepository<T> where T : class
{
// Marks an entity as new
void Add(T entity);
// Marks an entity as modified
void Update(T entity);
// Marks an entity to be removed
void Delete(T entity);
void Delete(Expression<Func<T, bool>> where);
// Get an entity by int id
T GetById(int id);
// Get an entity using delegate
T Get(Expression<Func<T, bool>> where);
// Gets all entities of type T
IEnumerable<T> GetAll();
// Gets entities using delegate
IEnumerable<T> GetMany(Expression<Func<T, bool>> where);
}
IUnitOfWork.cs
public interface IUnitOfWork
{
void Commit();
}
RepositoryBase.cs
public abstract class RepositoryBase<T> where T : class
{
#region Properties
private WilMpeContext _dataContext;
private readonly IDbSet<T> _dbSet;
protected IDbFactory DbFactory
{
get;
private set;
}
protected WilMpeContext DbContext
{
get { return _dataContext ?? (_dataContext = DbFactory.Init()); }
}
#endregion
protected RepositoryBase(IDbFactory dbFactory)
{
DbFactory = dbFactory;
_dbSet = DbContext.Set<T>();
}
#region Implementation
public virtual void Add(T entity)
{
_dbSet.Add(entity);
}
public virtual void Update(T entity)
{
_dbSet.Attach(entity);
_dataContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
_dbSet.Remove(entity);
}
public virtual void Delete(Expression<Func<T, bool>> where)
{
IEnumerable<T> objects = _dbSet.Where<T>(where).AsEnumerable();
foreach (T obj in objects)
_dbSet.Remove(obj);
}
public virtual T GetById(int id)
{
return _dbSet.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return _dbSet.ToList();
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).ToList();
}
public T Get(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).FirstOrDefault<T>();
}
#endregion
}
UnitOfWork.cs
public class UnitOfWork : IUnitOfWork
{
private readonly IDbFactory _dbFactory;
private WilMpeContext _dbContext;
public UnitOfWork(IDbFactory dbFactory)
{
this._dbFactory = dbFactory;
}
public WilMpeContext DbContext
{
get { return _dbContext ?? (_dbContext = _dbFactory.Init()); }
}
public void Commit()
{
DbContext.Commit();
}
}
WilMpeContext.cs - this is one of my DbContexts but now I need another and I'm not sure how to implement that with my existing design
public class WilMpeContext : IdentityDbContext<ApplicationUser>
{
public WilMpeContext()
: base("name=DefaultConnection", throwIfV1Schema: false) { }
public IDbSet<AppSetting> AppSettings { get; set; }
//the rest of the tables were removed for brevity
public virtual void Commit()
{
base.SaveChanges();
}
public static WilMpeContext Create()
{
return new WilMpeContext();
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
Here is how I setup the repository to use the unit of work. AppSetting is a table in my model:
public interface IAppSettingRepository : IRepository<AppSetting>
{
void UpdateAppSetting(AppSetting appSetting);
}
public class AppSettingRepository : RepositoryBase<AppSetting>,IAppSettingRepository
{
public AppSettingRepository(IDbFactory dbFactory)
: base(dbFactory) { }
//an example of how I do something in the database. See I use DbContext from RepositoryBase
public void UpdateAppSetting(AppSetting appSetting)
{
DbContext.Entry(appSetting).State = EntityState.Modified;
}
}
And this is my service:
public class AppSettingService : IAppSettingService
{
private readonly IAppSettingRepository _appSettingRepository;
private readonly IUnitOfWork _unitOfWork;
public AppSettingService(IAppSettingRepository appSettingRepository,
IUnitOfWork unitOfWork)
{
_appSettingRepository = appSettingRepository;
_unitOfWork = unitOfWork;
}
//call repository to do database stuff and then commit changes
public void UpdateAppSetting(AppSetting appSetting)
{
_appSettingRepository.UpdateAppSetting(appSetting);
_unitOfWork.Commit();
}
}
You need to make all your interfaces and classes that is using your current WilMpeContext to generic. Also you would need to put a generic constraint on new generic.
First make your Interfaces generic for Unit of work and DBFactory:
public interface IUnitOfWork<TContext> where TContext: DbContext, new()
{
void Commit();
}
public interface IDbFactory<TContext> : IDisposable where TContext: DbContext, new()
{
TContext Init();
}
Now let's update your Classes for UnitOfWork and DBFactory:
public class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext: DbContext, new()
{
private readonly IDbFactory<TContext> _dbFactory;
private TContext _dbContext;
public UnitOfWork(IDbFactory<TContext> dbFactory)
{
this._dbFactory = dbFactory;
}
public TContext DbContext
{
get { return _dbContext ?? (_dbContext = _dbFactory.Init()); }
}
public void Commit()
{
this.DbContext.SaveChanges();
}
}
public class DbFactory<TContext> : Disposable, IDbFactory<TContext> where TContext: DbContext, new()
{
TContext _dbContext;
public TContext Init()
{
return _dbContext ?? (_dbContext = new TContext());
}
protected override void DisposeCore()
{
_dbContext?.Dispose();
}
}
Add an additional generic on Repository base class:
public abstract class RepositoryBase<T, TContext> where T : class where TContext: DbContext, new()
{
#region Properties
private TContext _dataContext;
private readonly IDbSet<T> _dbSet;
protected IDbFactory<TContext> DbFactory
{
get;
private set;
}
protected TContext DbContext
{
get { return _dataContext ?? (_dataContext = this.DbFactory.Init()); }
}
#endregion
protected RepositoryBase(IDbFactory<TContext> dbFactory)
{
DbFactory = dbFactory;
_dbSet = DbContext.Set<T>();
}
#region Implementation
public virtual void Add(T entity)
{
_dbSet.Add(entity);
}
public virtual void Update(T entity)
{
_dbSet.Attach(entity);
_dataContext.Entry(entity).State = System.Data.Entity.EntityState.Modified;
}
public virtual void Delete(T entity)
{
_dbSet.Remove(entity);
}
public virtual void Delete(Expression<Func<T, bool>> where)
{
IEnumerable<T> objects = _dbSet.Where<T>(where).AsEnumerable();
foreach (T obj in objects)
_dbSet.Remove(obj);
}
public virtual T GetById(int id)
{
return _dbSet.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return _dbSet.ToList();
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).ToList();
}
public T Get(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).FirstOrDefault<T>();
}
#endregion
}
Here is your repository that will be typed with your Actual Context WilMpeContext class.
public class AppSettingRepository : RepositoryBase<AppSetting, WilMpeContext>, IAppSettingRepository
{
public AppSettingRepository(IDbFactory<WilMpeContext> dbFactory)
: base(dbFactory) { }
//an example of how I do something in the database. See I use DbContext from RepositoryBase
public void UpdateAppSetting(AppSetting appSetting)
{
DbContext.Entry(appSetting).State = System.Data.Entity.EntityState.Modified;
}
}
Finally your AppsettingService
public class AppSettingService : IAppSettingService
{
private readonly IAppSettingRepository _appSettingRepository;
private readonly IUnitOfWork<WilMpeContext> _unitOfWork;
public AppSettingService(IAppSettingRepository appSettingRepository,
IUnitOfWork<WilMpeContext> unitOfWork)
{
_appSettingRepository = appSettingRepository;
_unitOfWork = unitOfWork;
}
//call repository to do database stuff and then commit changes
public void UpdateAppSetting(AppSetting appSetting)
{
_appSettingRepository.UpdateAppSetting(appSetting);
_unitOfWork.Commit();
}
}
Now your UnitOfWork infrastructure will support any DbContext for all repositories.
Udpate
Alternative solution(May be)
May be I'm wrong but why would you need multiple dbcontext if your dbContext is not shared across the applications. I'm sure you are using Asp.net 5 MVC project that generates it's own IdenityDbContext and you might have your other DBContext as well. You can merge these two context and this way you can keep your current implementation of UOW.
Check out these SO QnA if this is the actual problem.
ASP.NET Identity DbContext confusion
Merge MyDbContext with IdentityDbContext
I've been at it for days, but I can't get Unity to inject anything with RegisterType<> into my Controller. I'm using Web Api 2, in Visual Studio 2015, with Unity 4. Whenever I try to inject IUnitOfWork or IRFContext, I get "message": "An error occurred when trying to create a controller of type 'ClPlayersController'. Make sure that the controller has a parameterless public constructor.".
I'm using the Unity.AspNet.WebApi to bootstrapp into WebApi. Below is my UnityWebApiActivator
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(mycompany.project.api.UnityWebApiActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(mycompany.project.api.UnityWebApiActivator), "Shutdown")]
namespace mycompany.project.api
{
public static class UnityWebApiActivator
{
public static void Start()
{
var resolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
I'm using a Start.cs due to Owin.
[assembly: OwinStartup(typeof(mycompany.project.api.Startup))]
namespace mycompany.project.api
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider(),
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
}
My WebApiConfig.cs is below:
namespace mycompany.project.api
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
log4net.Config.XmlConfigurator.Configure();
config.MapHttpAttributeRoutes();
config.EnableSystemDiagnosticsTracing();
config.Services.Add(typeof(IExceptionLogger),
new SimpleExceptionLogger(new LogManagerAdapter()));
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
}
}
}
My UnityConfig.cs is below
namespace mycompany.project.api
{
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
public static void RegisterTypes(IUnityContainer container)
{
var config = new MapperConfiguration(cfg =>
{
//AutoMapper bindings
});
container.RegisterInstance<IMapper>(config.CreateMapper());
container.RegisterType<IRFContext, RFContext>(new PerThreadLifetimeManager());
container.RegisterType<IUnitOfWork, UnitOfWork>();
XmlConfigurator.Configure();
var logManager = new LogManagerAdapter();
container.RegisterInstance<ILogManager>(logManager);
}
}
}
All that I have in my Global.asax is below:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Error()
{
var exception = Server.GetLastError();
if (exception != null)
{
var log = new LogManagerAdapter().GetLog(typeof(WebApiApplication));
log.Error("Unhandled exception.", exception);
}
}
}
If my Controller is like this, it works fine:
public class ClPlayersController : ApiController
{
private readonly IMapper mapper;
public ClPlayersController(IMapper _mapper, IUnityContainer container)
{
mapper = _mapper;
}
But placing IUnitOfWork, like below, or the IRFContext, I get the error:
private readonly IMapper mapper;
private readonly IUnitOfWork unitOfWork;
public ClPlayersController(IMapper _mapper, IUnityContainer container, IUnitOfWork _unitOfWork)
{
mapper = _mapper;
unitOfWork = _unitOfWork;
}
I can't find, for the life of me, what I'm doing wrong. If I loop through the container.Registrations on the constructor, I find the mappings, but they refuse to get injected. Any hints?
EDIT
Below is the code for UnitOfWork and RFContext
namespace mycompany.project.data.configuracao
{
public class UnitOfWork : IUnitOfWork
{
private readonly IRFContext _rfContext;
private bool _disposed = false;
public UnitOfWork(IRFContext rfContext)
{
_rfContext = rfContext;
}
public void Commit()
{
if (_disposed)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
_rfContext.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing && _rfContext != null)
{
_rfContext.Dispose();
}
_disposed = true;
}
}
}
and
namespace mycompany.project.data.configuracao
{
public interface IUnitOfWork : IDisposable
{
void Commit();
}
}
and RFContext is a basic POCO generated DBContext
namespace mycompany.project.data.configuracao
{
using System.Linq;
public class RFContext : System.Data.Entity.DbContext, IRFContext
{
public System.Data.Entity.DbSet<ClGrupoEconomico> ClGrupoEconomicoes { get; set; }
//all my DbSets
public System.Data.Entity.DbSet<SpTipoLog> SpTipoLogs { get; set; }
static RFContext()
{
System.Data.Entity.Database.SetInitializer<RFContext>(null);
}
public RFContext()
: base("Name=RFContext")
{
}
public RFContext(string connectionString)
: base(connectionString)
{
}
public RFContext(string connectionString, System.Data.Entity.Infrastructure.DbCompiledModel model)
: base(connectionString, model)
{
}
public RFContext(System.Data.Common.DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{
}
public RFContext(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, bool contextOwnsConnection)
: base(existingConnection, model, contextOwnsConnection)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new ClGrupoEconomicoConfiguration());
//all my Configuration classes
modelBuilder.Configurations.Add(new SpTipoLogConfiguration());
}
public static System.Data.Entity.DbModelBuilder CreateModel(System.Data.Entity.DbModelBuilder modelBuilder, string schema)
{
modelBuilder.Configurations.Add(new ClGrupoEconomicoConfiguration(schema));
//all my configuration classes
modelBuilder.Configurations.Add(new SpTipoLogConfiguration(schema));
return modelBuilder;
}
}
}
Unfortunately the exception you are seeing can occur for several reasons. One of them is when Unity cannot resolve one or more of your injections.
An error occurred when trying to create a controller of type
'FooController'. Make sure that the controller has a parameterless
public constructor.
So, based on the information in your question your setup is apparently correct, since IMapper can be injected. Therefore I guess that UnitOfWork and RFContext have dependencies that Unity cannot resolve. Maybe a repository?
UPDATE:
The problem here is that your RFContext has several constructors.
https://msdn.microsoft.com/en-us/library/cc440940.aspx#cnstrctinj_multiple
When a target class contains more than one constructor with the same
number of parameters, you must apply the InjectionConstructor
attribute to the constructor that the Unity container will use to
indicate which constructor the container should use. As with automatic
constructor injection, you can specify the constructor parameters as a
concrete type, or you can specify an interface or base class for which
the Unity container contains a registered mapping.
In this case Unity doesn't know how to resolve your RFContext, and will try to use the constructor with the most parameters. You can solve it by using
container.RegisterType<IRFContext, RFContext>(new InjectionConstructor());
Have been implementing Generic Repository, Unit of Work pattern with EF5 Code First from a number of resources and have come up with the following assemblies.
Interfaces, Contexts, Model, Repositories, UnitsOfWork
In the Context assembly I have my migrations folder which contains Configuration.cs
internal sealed class Configuration : DbMigrationsConfiguration<Context.SportsContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(Context.SportsContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
As you can see this DbMigrationsConfiguration takes in my SportsContext which is also defined in the contexts assembly (Contexts folder)
public class SportsContext : IDbContext
{
private readonly DbContext _context;
public SportsContext()
{
_context = new DbContext("SportsContext");
}
public void Dispose()
{
_context.Dispose();
}
public IDbSet<T> GetEntitySet<T>() where T : class
{
return _context.Set<T>();
}
public void ChangeState<T>(T entity, EntityState state) where T : class
{
_context.Entry(entity).State = state;
}
public void SaveChanges()
{
_context.SaveChanges();
}
}
This implements IDbContext which is defined in the Interfaces assembly
public interface IDbContext : IDisposable
{
IDbSet<T> GetEntitySet<T>() where T : class;
void ChangeState<T>(T entity, EntityState state) where T : class;
void SaveChanges();
}
In my UnitsOfWork assembly I have the following class
public class SportUnitOfWork : IUnitofWork
{
private readonly IDbContext _context;
public SportUnitOfWork()
{
_context = new SportsContext();
}
private GenericRepository<Team> _teamRepository;
private GenericRepository<Fixture> _fixtureRepository;
public GenericRepository<Team> TeamRepository
{
get { return _teamRepository ?? (_teamRepository = new GenericRepository<Team>(_context)); }
}
public GenericRepository<Fixture> FixtureRepository
{
get { return _fixtureRepository ?? (_fixtureRepository = new GenericRepository<Fixture>(_context)); }
}
public void Save()
{
_context.SaveChanges();
}
public IDbContext Context
{
get { return _context; }
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_context.Dispose();
}
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
For examples sake I have added the GenericRepository class in the Repositories assembly
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private IDbContext _context;
public GenericRepository(IDbContext context)
{
_context = context;
}
public GenericRepository(IUnitofWork uow)
{
_context = uow.Context;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposing) return;
if (_context == null) return;
_context.Dispose();
_context = null;
}
public void Add(T entity)
{
_context.GetEntitySet<T>().Add(entity);
}
public void Update(T entity)
{
_context.ChangeState(entity, EntityState.Modified);
}
public void Remove(T entity)
{
_context.ChangeState(entity, EntityState.Deleted);
}
public T FindSingle(Expression<Func<T, bool>> predicate = null, params Expression<Func<T, object>>[] includes)
{
var set = FindIncluding(includes);
return (predicate == null) ? set.FirstOrDefault() : set.FirstOrDefault(predicate);
}
public IQueryable<T> Find(Expression<Func<T, bool>> predicate = null, params Expression<Func<T, object>>[] includes)
{
var set = FindIncluding(includes);
return (predicate == null) ? set : set.Where(predicate);
}
public IQueryable<T> FindIncluding(params Expression<Func<T, object>>[] includeProperties)
{
var set = _context.GetEntitySet<T>();
if (includeProperties != null)
{
foreach (var include in includeProperties)
{
set.Include(include);
}
}
return set.AsQueryable();
}
public int Count(Expression<Func<T, bool>> predicate = null)
{
var set = _context.GetEntitySet<T>();
return (predicate == null) ? set.Count() : set.Count(predicate);
}
public bool Exist(Expression<Func<T, bool>> predicate = null)
{
var set = _context.GetEntitySet<T>();
return (predicate == null) ? set.Any() : set.Any(predicate);
}
}
The problem I have is in the Configuration class which inherits from DbMigrationsConfiguration is expecting a DbContext parameter.
Error is Error 1 The type 'Contexts.Context.SportsContext' cannot be used as type parameter 'TContext' in the generic type or method 'System.Data.Entity.Migrations.DbMigrationsConfiguration'. There is no implicit reference conversion from 'Contexts.Context.SportsContext' to 'System.Data.Entity.DbContext'.
I can change the SportsContext to also inherit from DbContext but then I need to add a reference to EntityFramework 5 in the UnitsOfWork assembly as we want to possibly change or take out each layer without any reference to underlying models which is why i went with this pattern.
As we are looking at adding further contexts and models in the future so wanted to setup a architecture in that we could just add the context, model and then implement the relevant interfaces as and when needed.
A WebAPI Restful Web Service will be interacting with our data via the SportUnitOfWork, if I have understood the patterns correctly.
If anyone has any ideas on how I could do this or anything that I am doing wrong please let me know
thanks in advance Mark
Resolved this by doing the following
Changed my SportsContext class to a BaseContext which is abstract
public abstract class BaseContext : IDbContext
{
protected DbContext Context;
public void Dispose()
{
Context.Dispose();
}
public IDbSet<T> GetEntitySet<T>() where T : class
{
return Context.Set<T>();
}
public void Add<T>(T entity) where T : class
{
DbEntityEntry dbEntityEntry = GetDbEntityEntrySafely(entity);
dbEntityEntry.State = EntityState.Added;
}
public void Update<T>(T entity) where T : class
{
DbEntityEntry dbEntityEntry = GetDbEntityEntrySafely(entity);
dbEntityEntry.State = EntityState.Modified;
}
public void Delete<T>(T entity) where T : class
{
DbEntityEntry dbEntityEntry = GetDbEntityEntrySafely(entity);
dbEntityEntry.State = EntityState.Deleted;
}
public void SaveChanges()
{
// At the moment we are conforming to server wins when handling concurrency issues
// http://msdn.microsoft.com/en-us/data/jj592904
try
{
Context.SaveChanges();
}
catch (DbUpdateConcurrencyException e)
{
//Refresh using ServerWins
var objcontext = ((IObjectContextAdapter) Context).ObjectContext;
var entry = e.Entries;
objcontext.Refresh(RefreshMode.StoreWins, entry);
SaveChanges();
}
}
private DbEntityEntry GetDbEntityEntrySafely<T>(T entity) where T : class
{
DbEntityEntry dbEntityEntry = Context.Entry(entity);
if (dbEntityEntry.State == EntityState.Detached)
{
// Set Entity Key
var objcontext = ((IObjectContextAdapter) Context).ObjectContext;
if (objcontext.TryGetObjectByKey(dbEntityEntry.Entity))
Context.Set<T>().Attach(entity);
}
return dbEntityEntry;
}
}
created in the Context folder a new class called FootballContext which inherits from BaseContext.
public class FootballContext : BaseContext
{
public FootballContext(string connectionstringName)
{
Context = new BaseFootballContext(connectionstringName);
}
}
Created a new folder called DbContexts
In here created the following classes,
public class BaseFootballContext : DbContext
{
public BaseFootballContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
public IDbSet<Fixture> Fixtures { get; set; }
public IDbSet<Team> Teams { get; set; }
}
public class MigrationsContextFactory : IDbContextFactory<BaseFootballContext>
{
public BaseFootballContext Create()
{
return new BaseFootballContext("FootballContext");
}
}
now my Configuration class can take in the BaseFootballContext as this is a DbContext.
My UnitOfWork class can now set the context to be FootballContext so does not have to reference EntityFramework.
This works with Migrations as well.
Only problem I have now is to figure out how to get this to work in a disconnected environment as I am having a problem reattaching entities and applying updates.
I'm playing with the latest Entity Framework CTP 5 release and building a simple asp.net MVC blog where I just have two tables: Post and Comments. This is done entirely in POCO, I just need help on the DbContext part, where I need it to be unit testable (using IDbSet?) and I need a simple/generic repository pattern for add, update, delete, retrieval. Any help is appreciated.
Thanks.
Start with you DbContext, create a new file called Database.cs:
Database.cs
public class Database : DbContext
{
private IDbSet<Post> _posts;
public IDbSet<Post> Posts {
get { return _posts ?? (_posts = DbSet<Post>()); }
}
public virtual IDbSet<T> DbSet<T>() where T : class {
return Set<T>();
}
public virtual void Commit() {
base.SaveChanges();
}
}
Define a IDatabaseFactory and implement it with DatabaseFactory:
IDatabaseFactory.cs
public interface IDatabaseFactory : IDisposable
{
Database Get();
}
DatabaseFactory.cs
public class DatabaseFactory : Disposable, IDatabaseFactory {
private Database _database;
public Database Get() {
return _database ?? (_database = new Database());
}
protected override void DisposeCore() {
if (_database != null)
_database.Dispose();
}
}
Disposable extension method:
Disposable.cs
public class Disposable : IDisposable
{
private bool isDisposed;
~Disposable()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(!isDisposed && disposing)
{
DisposeCore();
}
isDisposed = true;
}
protected virtual void DisposeCore()
{
}
}
Now we can define our IRepository and our RepositoryBase
IRepository.cs
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
T GetById(long Id);
IEnumerable<T> All();
IEnumerable<T> AllReadOnly();
}
RepositoryBase.cs
public abstract class RepositoryBase<T> where T : class
{
private Database _database;
private readonly IDbSet<T> _dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
_dbset = Database.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get; private set;
}
protected Database Database
{
get { return _database ?? (_database = DatabaseFactory.Get()); }
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
_dbset.Remove(entity);
}
public virtual void Update(T entity)
{
_database.Entry(entity).State = EntityState.Modified;
}
public virtual T GetById(long id)
{
return _dbset.Find(id);
}
public virtual IEnumerable<T> All()
{
return _dbset.ToList();
}
public virtual IEnumerable<T> AllReadOnly()
{
return _dbset.AsNoTracking().ToList();
}
}
Now you can create your IPostRepository and PostRepository:
IPostRepository.cs
public interface IPostRepository : IRepository<Post>
{
//Add custom methods here if needed
Post ByTitle(string title);
}
PostRepository.cs
public class PostRepository : RepositoryBase<Post>, IPostRepository
{
public PostRepository(IDatabaseFactory databaseFactory) : base(databaseFactory)
{
}
public Post ByTitle(string title) {
return base.Database.Posts.Single(x => x.Title == title);
}
}
Lastly, the UoW:
IUnitOfWork.cs
public interface IUnitOfWork
{
void Commit();
}
UnitOfWork.cs
private readonly IDatabaseFactory _databaseFactory;
private Database _database;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
_databaseFactory = databaseFactory;
}
protected Database Database
{
get { return _database ?? (_database = _databaseFactory.Get()); }
}
public void Commit()
{
Database.Commit();
}
Using in your controller:
private readonly IPostRepository _postRepository;
private readonly IUnitOfWork_unitOfWork;
public PostController(IPostRepository postRepository, IUnitOfWork unitOfWork)
{
_postRepository = postRepository;
_unitOfWork = unitOfWork;
}
public ActionResult Add(Post post) {
_postRepository.Add(post);
_unitOfWork.Commit();
}
You will need to use an IoC container like StructureMap to make this work. You can install structure map via NuGet, or if you are using MVC 3, you can install the StructureMap-MVC NuGet package. (Links Below)
Install-Package StructureMap.MVC4
Install-Package StructureMap.MVC3
Install-Package Structuremap
If you have questions just let me know. Hope it helps.
I just love this in-depth article about Entity Framework 4 POCO, Repository and Specification Pattern
http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/
The only thing I'd do differently is in the implementation, i.e. expose the IPostRepository in the service layer and have an interface field of type IPostService in the controller just as another layer of abstraction but otherwise this is a good example - nice one, Paul.