I have a weird situation. I need to use Entity Framework 6.2 for my .net core app.
An ordinary Controller
public class SampleApiController : BaseController
{
// use _repo and other stuff
}
Base Controller
public class BaseController : Controller
{
protected IRepo_repository;
public BaseController(IRepo repository)
{
_repository = repository;
}
public BaseController() : this(null)
{
}
}
App DBContext
public class SampleContext : DbContext
{
public SampleContext(string connectionString)
:base(connectionString)
{
try
{
this.Database.Log = (s) => System.Diagnostics.Debug.Write(s);
}
catch (Exception e)
{
//CurrentLogger.Log.Error(e);
}
}
public DbSet<Test1> Test1s { get; set; }
public DbSet<Test2> Test2s { get; set; }
}
Repository interface
public interface IRepo
{
// methods definition
}
Repository class
public interface Repo : IRepo
{
// methods implementation
}
Startup.cs -> ConfigureServices method
services.AddScoped<SampleContext>((s) => new SampleContext(configuration["ConnectionStrings:SampleApp"]));
services.AddScoped<IRepo, Repo>();
In this picture you could see that repository param is empty... not initialized with Repo instance... (!!! In this picture IRepo is IRepositoryBase)
Solution !
As CodeNotFound and Riscie said in comments, the problem was that BaseController was initialized with null... Thanks guys!
Try this:
Repository interface
public interface IRepo
{
// methods definition
}
Repository class
I have changed this from interface to class and made it implement the IRepo Interface
public class Repo : IRepo
{
// methods implementation
}
Edit: Also remove the second constructor
public class BaseController : Controller
{
protected IRepo_repository;
public BaseController(IRepo repository)
{
_repository = repository;
}
//second constructor most likely introduces the problem
}
You normally pass IRepo from SampleApiController to BaseController.
Base on my understanding, you do not need no argument constructor in BaseController. If so, you might want to remove it to prevent _repository being null.
public class SampleApiController : BaseController
{
public SampleApiController(IRepo repository)
: base(repository)
{
}
}
public class BaseController : Controller
{
protected IRepo _repository;
public BaseController(IRepo repository)
{
_repository = repository;
}
/*public BaseController() : this(null)
{
}*/
}
public interface IRepo
{
// methods definition
}
Related
I am struggling to register with Autofac a hierarchy of classes and interfaces.
I have an interface IMyService defined as below:
public interface IMyService
{
void DoMyService();
}
And I have two abstract classes with implement this interface and called MyServiceA, and MyServiceB:
public abstract class MyServiceA : IMyService
{
public abstract DoMyService();
}
public abstract class MyServiceB : IMyService
{
public abstract DoMyService();
}
Moreover I have a second-level hierarchy for each of the two aforementioned services: MyServiceA1, MyServiceA2, MyServiceB1 and MyServiceB2:
public class MyServiceA1 : MyServiceA
{
public MyServiceA1() : base() {}
public void DoMyService()
{
// Implementation goes here
}
}
public class MyServiceA2 : MyServiceA
{
public MyServiceA2() : base() {}
public void DoMyService()
{
// Implementation goes here
}
}
public class MyServiceB1 : MyServiceB
{
public MyServiceB1() : base() {}
public void DoMyService()
{
// Implementation goes here
}
}
public class MyServiceB2 : MyServiceB
{
public MyServiceB2() : base() {}
public void DoMyService()
{
// Implementation goes here
}
}
I have in input two enums FirstEnum and SecondEnum used to select which of the four concrete types to instantiate:
public enum FirstEnum
{
SvcA,
SvcB
}
public enum SecondEnum
{
Svc1,
Svc2
}
I want to register IMyService and by providing two enums, It will automatically instantiate the good concrete type.
For instance, if I want to resolve an IMyService and I provide FirstEnum.SvcB and SecondEnum.Svc2, it should instantiate the concrete type MyServiceB2 class. Moreover this hierarchy might be updated by adding some other concrete types etc, so I need a generic way of doing it
Does anyone have a clue to help me?
Thanks
If you want to create a specific service dynamically depending on a set of parameters, this is a good use case for an abstract factory:
public interface IMyServiceFactory
{
IMyService Create(FirstEnum e1, SecondEnum e2);
}
public class MyServiceFactory : IMyServiceFactory
{
private readonly ILifetimeScope scope;
public MyServiceFactory(ILifetimeScope scope)
{
if (scope == null)
throw new ArgumentNullException("scope");
this.scope = scope;
}
public IMyService Create(FirstEnum e1, SecondEnum e2)
{
if (e1 == FirstEnum.SvcA)
{
if (e2 == SecondEnum.Svc1)
{
return scope.Resolve<MyServiceA1>();
}
else //svc2
{
return scope.Resolve<MyServiceA2>();
}
}
else //B
{
if (e2 == SecondEnum.Svc1)
{
return scope.Resolve<MyServiceB1>();
}
else //svc2
{
return scope.Resolve<MyServiceB2>();
}
}
}
}
And now your consumer need to get the factory injected instead of the service:
public class MyServiceConsumer
{
private readonly IMyServiceFactory factory;
public MyServiceConsumer(IMyServiceFactory factory)
{
this.factory = factory;
}
public void Do()
{
//var service = this.factory.Create
}
}
Registration :
Autofac.ContainerBuilder builder = new Autofac.ContainerBuilder();
builder.RegisterType<MyServiceA1>().AsSelf().AsImplementedInterfaces();
builder.RegisterType<MyServiceA2>().AsSelf().AsImplementedInterfaces();
builder.RegisterType<MyServiceB1>().AsSelf().AsImplementedInterfaces();
builder.RegisterType<MyServiceB2>().AsSelf().AsImplementedInterfaces();
builder.RegisterType<MyServiceFactory>().As<IMyServiceFactory>();
builder.RegisterType<MyServiceConsumer>();
//and quick test resolve
var container = builder.Build();
var test = container.Resolve<MyServiceConsumer>();
I have just landed in dependency injection world.
I have the following custom DbContext-
public partial class SkyTrackerContext: DbContext
{
public SkyTrackerContext(): base()
{
Database.SetInitializer(new SkyTrackerDBInitializer());
}
}
Would like inject SkyTrackerContext in this base controller-
public abstract class BaseController : Controller
{
public BaseController() {}
[Inject]
public SkyTrackerContext MyDbContext { get; set; }
}
Sample usage-
public class LoginController : BaseController
{
public ActionResult ValidateLogin(Login login)
{
var query = MyDbContext.Persons.Where(.....);
}
}
What should I write in NinjectWebCommon.cs to inject this context ?
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
First, you should avoid method injection. Instead, use constructor injection. In other words:
public abstract class BaseController : Controller
{
protected readonly DbContext context;
public BaseController(DbContext context)
{
this.context = context;
}
...
}
Then, as far as the Ninject config goes, it's extremely simple:
kernel.Bind<DbContext>().To<SkyTrackerContext>().InRequestScope();
I have an autofac DI in my project.
I want to expose an interface by conventional which all other interfaces of my project will inherit from. Is it possible to automatically register the components of the inherited interfaces at start up level? For example:
Public interface IConvetionInterface {}
public interface IImplementationA:IConvetionInterface
{
public void DoSomethingA();
}
public interface IImplementationB:IConvetionInterface
{
public void DoSomethingB();
}
Injecting through constructor;
public class ConsumerA
{
private readonly IImplementationA _a;
public DealerRepository(IImplementationA A)
{
_a= A;
}
public Act()
{
_a.DoSomethingA();
}
}
How do I register IConvetionInterface to make all its dependencies resolve in Autofac.
I have been able to come up with this solution by using autofac Assembly Scanning Configuration as provided in their documentation page Autofac Documentation Page
I have an open generic interface
public interface IRepository<TEntity, TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey>
{ }
Implemented by
public class Repository<TEntity, TPrimaryKey> : RepositoryBase<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>{}
Then, I created an empty interface
public interface IConventionDependency
{
}
This method was called to register my components at startup level:
public static void RegisterAPSComponents(ContainerBuilder builder)
{
builder.RegisterType<APSContext>().InstancePerRequest();
builder.RegisterGeneric(typeof(Repository<,>)).As(typeof(IRepository<,>)).InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(typeof(IConventionDependency).Assembly).AssignableTo<IConventionDependency>().As<IConventionDependency>().AsImplementedInterfaces().AsSelf().InstancePerLifetimeScope();
}
By the above registration, any interface that inherits from IConventionDependency will be registered automatically in the container.
example:
create an interface:
public interface IDealerRepository : IConventionDependency
{
List<Dealers> GetDealers();
}
then Implement the interface :
public class DealerRepository : IDealerRepository
{
private readonly IRepository<VTBDealer, int> _repository;
public DealerRepository(IRepository<VTBDealer, int> repository)
{
_repository = repository;
}
public List<Dealers> GetDealers()
{
return _repository.GetAllList().MapTo<List<Dealers>>();
}
}
in conclusion, without explicitly registering IDealerRepository, it gets resolved in MVC Controller constructor.
I would like to how to correct build and handle with NHibernate repository and session in view models classes.
For example I use Caliburn Micro framework with Castle Windsor boostraper.
First I created NHibernate repository:
public interface IRepository{//I omitted not needed code for simplification}
public class NHibRepository: IRepository
{
private ISession _session;
public NHibRepository(ISession session)
{
_session=session;
}
// I omitted not needed code for simplification
}
Second I definied some POCO class and mapping class with Fluent NHibernate.
public class User{}
public class Profile{}
public class Album{}
public class UserMap : ClassMap<User>{}
public class ProfileMap : ClassMap<Profile>{}
public class AlbumMap : ClassMap<Album>{}
Now I need use NHibernate repositories in my view models.
public interface IViewModelA{}
public class ViewModelA : ScreenViewModel, IViewModelA
{
public NHibRepository<User> UserRepo{get;set;}
public NHibRepository<Profile> ProfileRepo{get;set;}
}
public interface IViewModelB{}
public class ViewModelB : Screen, IViewModelB
{
public NHibRepository<Profile> ProfileRepo{get;set;}
public NHibRepoistory<Album> AlbumRepo{get;set;}
}
When I am creating repository class for some entity class I need pass session to NHibRepository construtor.
UserRepo= new NHibRepository<User>(NHIBERNATE SESSION);
Until now I used some helper class for creating Nhibernate session and init repository.
Helper class is here:
public class FluentNHibHelper
{
private ISessionFactory _sessionFactory;
public FluentNHibHelper(IPersistenceConfigurer db, Assembly asm)
{
InitializeSessionFactory(db, asm);
}
private void InitializeSessionFactory(IPersistenceConfigurer db, Assembly asm)
{
_sessionFactory = Fluently.Configure()
.Database(db)
.Mappings(m => m.FluentMappings.AddFromAssembly(asm))
.ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(true, true))
.BuildSessionFactory();
}
public ISession OpenSession()
{
return _sessionFactory.OpenSession();
}
}
with this class I created repository class:
private const string ConnString =
#"Server=TestMachine\SQLEXPRESS;Database=TEST;Trusted_Connection=True;";
UserRepo = new NHibRepository<User>(
new FluentNHibHelper(MsSqlConfiguration.MsSql2008.ConnectionString(ConnString),
Assembly.GetExecutingAssembly())
.OpenSession());
Now I am confuse I don’t what is the best way for creating repository object in view models.
For example in bootstraper class can I somehow register repository class ?
public class CastleBootstrapper : Bootstrapper<IShellViewModel>
{
private IWindsorContainer _windsorContainer;
protected override void Configure()
{
_windsorContainer = new WindsorContainer();
//register repository class here ???
}
}
Can anybody help me? Thank you very much
Sorry for my english.
I use the following in an ASP.net MVC application. Castle.Windsor takes care of creating the ISession dependency for each repository.
//Located in your application startup
protected IWindsorContainer CreateContainer()
{
container = new WindsorContainer();
container.Install(
new PersistenceInstaller(),
new RepositoryInstaller()
//, other installers here
);
return container;
}
public class PersistenceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<PersistenceFacility>();
}
}
public class PersistenceFacility : AbstractFacility
{
protected override void Init()
{
NHibernate.Cfg.Configuration config = BuildDatabaseConfiguration();
Kernel.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod(config.BuildSessionFactory),
Component.For<ISession>()
.UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
.LifeStyle.Trasient
);
}
private NHibernate.Cfg.Configuration BuildDatabaseConfiguration()
{
return Fluently.Configure()
.Database(SetupDatabase)
.Mappings(m => m.HbmMappings.AddFromAssemblyOf<Entity>())
.ExposeConfiguration(ConfigurePersistence)
.BuildConfiguration();
}
protected virtual IPersistenceConfigurer SetupDatabase()
{
return MsSqlConfiguration.MsSql2008
.UseOuterJoin()
.ConnectionString(x => x.FromConnectionStringWithKey("ApplicationServices"))
.ShowSql();
}
protected virtual void ConfigurePersistence(NHibernate.Cfg.Configuration config)
{
SchemaMetadataUpdater.QuoteTableAndColumns(config);
}
protected virtual bool IsDomainEntity(Type t)
{
return typeof(DomainBase).IsAssignableFrom(t);
}
}
public class RepositoryInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Find().Configure(ConfigureLifeStyle()));
}
private ConfigureDelegate ConfigureLifeStyle()
{
return c => c.LifeStyle.Transient;
}
private BasedOnDescriptor Find()
{
return AllTypes.FromAssemblyContaining<NHRepository>()
.Where(type => type.Name.EndsWith("Repository"))
.WithService
.AllInterfaces();
}
}
i am creating custom membership provider using ninject for binding to sql classes.
my class in looks like
public MyMembershipProvider(IUsersRepository userRepository)
{
this.userRepository = userRepository;
}
How can i create from this parameterless constructor?
kernel.Bind<IUsersRepository>().To<UsersRepository>();
kernel.Bind<MembershipProvider>().To<MyMembershipProvider>();
and then:
public class AccountController : Controller
{
private readonly MembershipProvider _membershipProvider;
public AccountController(MembershipProvider membershipProvider)
{
_membershipProvider = membershipProvider;
}
public ActionResult Foo()
{
// TODO: Use the membership provider to do some processing
return View();
}
}