InvalidOperationException: Unable to resolve service for type with EF dbcontext - .net-core

I am trying to use Dependency Injection for DB context. I am not sure what i am doing wrong but even after following all the steps i still get the error
Below are the steps that i follow ,suggest me where its going wrong. I am using multi tier project hence my repositories are in my DB access layer and controller in a mvc api application
My DB Context class
public partial class TestDbContext: DbContext
{
public TestDbContext(DbContextOptions<TestDbContext> options)
: base(options)
{
}
public virtual DbSet<Table1> Table1{ get; set; }
}
public interface IRepository<T> where T : class
{
IQueryable<T> GetDbSet();
}
public class Repository<T> : IRepository<T> where T : class
{
protected DbContext _entities;
protected readonly DbSet<T> _dbset;
public Repository(DbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public virtual IQueryable<T> GetDbSet()
{
return _dbset;
}
}
pulbic interface IUserRepository
{
List<UsersInfo> GetUsers();
}
public class UserRepository:IUserRepository
{
private readonly IRepository<Table1> table1repo;
public UserRepository(IRepository<Table1> _table1Repo)
{
table1repo = _table1Repo;
}
public List<UsersInfo> GetUsers()
{
return table1repo.GetDbSet().ToList();
}
}
public class MyController : : ControllerBase
{
private readonly IUserRepository _UserRepo;
public MyController (IUserRepository UserRepo)
{
_UserRepo= clientInfo;
}
[HttpGet]
public async Task<IActionResult> Get()
{
try
{
var result = _UserRepo.GetUsers();
return new JsonResult(result) { SerializerSettings = new JsonSerializerSettings() { Formatting = Formatting.Indented } };
}
catch(Exception e)
{
throw e;
}
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
services.Configure<IISOptions>(options =>
{
options.AutomaticAuthentication = false;
});
services.AddDbContext<TestDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ConnectionString")));
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Your context type in your repository class should be TestDbContext instead of DbContext.
public class Repository<T> : IRepository<T> where T : class
{
protected TestDbContext _entities;
protected readonly DbSet<T> _dbset;
public Repository(TestDbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public virtual IQueryable<T> GetDbSet()
{
return _dbset;
}
}

Related

Entity Framework Multiple Connections Error

I have a scenario wherein I have multiple connection strings defined under appsettings.json like this:
"ConnectionString": {
"ConnectionZone1": "Server=(localdb)\\mssqllocaldb;Database=Blogging;Trusted_Connection=True;",
"ConnectionZone2": "Server=localhost;Database=Blogging;Trusted_Connection=True;"
},
This I have registered in my startup.cs file as well:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DbContextZone1>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ConnectionZone1")));
services.AddDbContext<DbContextZone2>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ConnectionZone2")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
I have created Model and context classes using database first approach, and registered my context classes as follows:
public partial class BloggingContext : DbContext
{
public BloggingContext()
{
}
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{
}
public virtual DbSet<Blog> Blog { get; set; }
public virtual DbSet<Post> Post { get; set; }
and created two other context classes which inherits from the above main base class:
public class DbContextZone1 : BloggingContext
{
public DbContextZone1()
{
}
}
public class DbContextZone2 : BloggingContext
{
public DbContextZone2()
{
}
}
Now I have created my API controllers and am trying to call these context methods.
[HttpGet]
public async Task<ActionResult<IEnumerable<object>>> GetItems()
{
if (alternate)
{
alternate = false;
using (var context = new DbContextZone1())
{
return await context.Blog.ToListAsync();
}
}
using(var context = new DbContextZone2())
{
return await context.Post.ToListAsync();
}
}
The issue is when I run my application it throws error that my context class should have parameterized constructor in order to pass options.
So in the DbContextZone1 and DbContextZone2 constructor which context options parameter will come?. I tried putting like this, but it never works and throws error when I call the API controller:
public class DbContextZone1 : BloggingContext
{
public DbContextZone1(DbContextOptions<BloggingContext> options)
: base(options)
{
}
}
public class DbContextZone2 : BloggingContext
{
public DbContextZone2(DbContextOptions<BloggingContext> options)
: base(options)
{
}
}
And this the error:
So any help or code ideas or suggestions in how to achieve multiple connections or make my code right?.
From your appsettings.json,it seems that you want to connect to the same database in different server.You are no need to create a base DbContext,just inherits default DbContext like below:
public class DbContextZone1 : DbContext
{
public DbContextZone1(DbContextOptions<DbContextZone1> options)
: base(options)
{
}
public virtual DbSet<Blog> Blog { get; set; }
}
public class DbContextZone2 :DbContext
{
public DbContextZone2(DbContextOptions<DbContextZone2> options)
: base(options)
{
}
public virtual DbSet<Post> Post { get; set; }
}
And call the API Controller like below:
private readonly DbContextZone1 _context1;
private readonly DbContextZone2 _context2;
public ABCController(DbContextZone1 context1, DbContextZone2 context2)
{
_context1 = context1;
_context2 = context2;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<object>>> GetItems()
{
//....
if (alternate)
{
alternate = false;
return await _context1.Blog.ToListAsync();
}
return await _context2.Post.ToListAsync();
}
Change Your DbContext Cunstructors to this:
public class DbContextZone1 : BloggingContext
{
public DbContextZone1(DbContextOptions<DbContextZone1> options)
: base(options)
{
}
}
public class DbContextZone2 : BloggingContext
{
public DbContextZone2(DbContextOptions<DbContextZone2> options)
: base(options)
{
}
}
Update:
If you've got errors after changing your DbContext class is because you're trying to access default constructors like below:
using (var context = new DbContextZone1())
when there is no implemented default constructor in your classes. As you've registered your DbContext classes in .net core DI system, you just need to inject DbContextZone1 and DbContextZone2 in Controller's constructor, and then you can easily access to contexts. But before doing that you should add your DbSet to DbContext classes and change them to:
public class DbContextZone1 : BloggingContext
{
public DbContextZone1(DbContextOptions<DbContextZone1> options)
: base(options)
{ }
public virtual DbSet<Blog> Blogs { get; set;}
}
public class DbContextZone2 : BloggingContext
{
public DbContextZone2(DbContextOptions<DbContextZone2> options)
: base(options)
{ }
public virtual DbSet<Post> Posts { get; set;}
}
Note: You can keep your DbSets in BloggingContext and then access them via _context in your controller but moving them like above makes your contexts isolated and gives single responsibility to the Contexts.
Now your Controller should be like this:
private readonly DbContextZone1 _context1;
private readonly DbContextZone2 _context2;
public MyController(DbContextZone1 context1, DbContextZone2 context2)
{
_context1 = context1;
_context2 = context2;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<object>>> GetItems()
{
if (alternate)
{
alternate = false;
return await _context1.Blogs.ToListAsync();
}
return await _context2.Posts.ToListAsync();
}

Inject automapper with Autofac in each Controller class

I want to inject the automapper in other layes of the application. I have read other posts and articles but I can't manage to figure out how to apply them. I am new to automapping and IoC. This is what I've tried by now. What can I change so that I automapper would be injected in controller and other layers?
public class AutomapperConfig
{
public MapperConfiguration Config { get; set; }
public void Initialize()
{
Config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<CustomerViewModel, CustomerBusinessModel>().ReverseMap();
...
}
}
public static IContainer BuildContainer()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
....
return builder.Build();
}
public class MvcApplication : System.Web.HttpApplication
{
public IContainer _container;
protected void Application_Start()
{ ...
_container = AutofacConfig.BuildContainer();
DependencyResolver.SetResolver(new AutofacDependencyResolver(_container));
}
}
public class CustomersController : Controller
{
private readonly IBusinessLogic<CustomerBusinessModel> _customerBl;
private readonly IMapper mapper;
public CustomersController (IBusinessLogic<CustomerBusinessModel> customer, AutomapperConfig automapper)
{
_customerBl= customer;
mapper = automapper.Config.CreateMapper();
}
...
}
Try this
builder.Register(c => new MapperConfiguration(cfg =>
{
cfg.CreateMap<CustomerViewModel, CustomerBusinessModel>().ReverseMap();
...
})
.AsImplementedInterfaces().SingleInstance();
builder.Register(c => c.Resolve<IConfigurationProvider>().CreateMapper())
.As<IMapper>();
CustomerController.cs
public class CustomersController : Controller
{
private readonly IBusinessLogic<CustomerBusinessModel> _customerBl;
private readonly IMapper _mapper;
public CustomersController (IBusinessLogic<CustomerBusinessModel> customer, IMapper mapper)
{
_customerBl= customer;
_mapper = mapper;
}

Unit Test issues with Entity FrameWork (nullable values)

im trying to implement a uniTest for my application so when i tried to get User by ID value in my application it's work fine, but when i tried to do the same scenario from my unit test class i always get nullable result even if the ID value is correct :
Class AccountController : ApiController
{
private UserService _UserService = null;
public AccountController()
{
_UserService = new UserService();
}
[AllowAnonymous]
[Route("test")]
public IHttpActionResult test()
{
var user = _UserService.getUserById(1); //user --> not null;
}
}
but when i tried a UnitTest Script
[TestClass]
public class userServiceTest
{
private UserService _UserService = null;
public userServiceTest()
{
_UserService = new UserService();
}
[TestMethod]
public void checkUserCase1()
{
var user = _UserService.getUserById(1); //user is null value !!!;
}
}
User Service :
public class UserService
{
private GenericRepository<User> _UserRepository = null;
public UserService()
{
_UserRepository = new GenericRepository<User>();
}
public User getUserById(int id)
{
return _UserRepository.Find(x => x.Id == id).FirstOrDefault();
}
}
The Generic Repository
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private MyDbContext db = null;
private DbSet<T> table = null;
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return table.Where(predicate);
}
}
IGeneric :
public interface IGenericRepository<T> where T : class
{
IEnumerable<T> SelectAll();
T SelectByID(object id);
void Insert(T obj);
void Update(T obj);
void Delete(object id);
void Save();
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
}
My DB Context :
public class MyDbContext : DbContext
{
public MyDbContext()
: base("AuthWebApiDb")
{
Database.SetInitializer<MyDbContext>(new MyDbInitializer());
}
public DbSet<User> Users { get; set; }
}
I have Two Project : One is the simple project, the second is the Unit Test
Check if EF is innstalled in your UnitTest project.
Put the connection string in the app.config file in the unitest project.
Thank's #Stewart_T

DbSet, DbContext, EntityFramework

I am new to ASP.NET and very new to EF. I am trying to develop an application and after reading some sites I've decided I'm going to create a 3-tier application (DAL, BL, a website as the frontend).
For the DAL layer I've taken inspiration from here
http://codefizzle.wordpress.com/2012/07/26/correct-use-of-repository-and-unit-of-work-patterns-in-asp-net-mvc/
public interface IGenericRepository<T> where T : class
{
void Add(T a);
}
public interface IUnitOfWork:IDisposable
{
IGenericRepository<UserInfo> UserInfoRepository { get; }
void Commit();
}
public class EfGenericRepository<T> : IGenericRepository<T> where T : class
{
private DbSet<T> _dbSet;
public EfGenericRepository(DbSet<T> dbSet)
{
_dbSet = dbSet;
}
public void Add(T a)
{
_dbSet.Add(a);
}
}
public class EfUnitOfWork : DbContext, IUnitOfWork
{
private readonly EfGenericRepository<UserInfo> _userInfoRepo;
public DbSet<UserInfo> UserInfos { get; set; }
public EfUnitOfWork()
{
_userInfoRepo = new EfGenericRepository<UserInfo>(UserInfos);
}
public IGenericRepository<UserInfo> UserInfoRepository
{
get { return _userInfoRepo; }
}
public void Commit()
{
this.SaveChanges();
}
}
and my BL looks like this:
public interface IBussinessLogic
{
void AddUserInfo(string c);
}
public class BusinessLogic: IBussinessLogic
{
private IUnitOfWork _unitOfWork;
public BusinessLogic()
{
_unitOfWork = new EfUnitOfWork();
}
public void AddUserInfo(string c)
{
_unitOfWork.UserInfoRepository.Add(new UserInfo()
{
Address = c
});
_unitOfWork.Commit();
}
}
Now I am using web-forms but I don't think that should be an issue.
On click i execute this:
IBussinessLogic businessLogic = new BusinessLogic();
businessLogic.AddUserInfo(address.Text);
But nothing happens,my data is not saved in the db.
Can anyone please help me?

Windsor ComponentNotFoundException IHttpControllerActivator

I have tried to implement Castle Windsor into my ASP.NET Web API project by following the guide by Mark Seemann. But when I try to run the code it gives me a ComponentNotFoundException exception. I mean that I should have registered the dependency right.
I really hope that someone has a solution to my problem. I have tried to search for a solution but with out any luck.
Global.asax
public class WebApiApplication : System.Web.HttpApplication
{
private readonly IWindsorContainer _container;
public WebApiApplication()
{
_container = new WindsorContainer().Install(new ControllerInstaller());
}
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new WindsorCompositionRoot(_container));
}
public override void Dispose()
{
_container.Dispose();
base.Dispose();
}
}
IHttpControllerActivator implementation
public class WindsorCompositionRoot : IHttpControllerActivator
{
private readonly IWindsorContainer _container;
public WindsorCompositionRoot(IWindsorContainer container)
{
_container = container;
}
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
var controller =
(IHttpController)_container.Resolve(controllerType);
request.RegisterForDispose(
new Release(
() => _container.Release(controller)));
return controller;
}
private class Release : IDisposable
{
private readonly Action release;
public Release(Action release)
{
this.release = release;
}
public void Dispose()
{
release();
}
}
}
ControllerInstaller
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IGymnastDataAccess>().ImplementedBy<GymnastDataAccess>());
}
}
Controller
public class GymnastController : ApiController
{
private readonly IGymnastDataAccess _gymnastDataAccess;
public GymnastController(IGymnastDataAccess gymnastDataAccess)
{
_gymnastDataAccess = gymnastDataAccess;
}
public IEnumerable<string> Get()
{
_gymnastDataAccess.Load();
return new string[] { "value1", "value2" };
}
}
Castle Windsor do not support automatic resolve of concrete classes out of the box, so you should register your controller class in container:
container.Register(Component.For<GymnastController>());
or implement ILazyComponentLoader like here to get automatic resolve of concrete classes.

Resources