I didn't understand this statement why using " : " colon sign is it inheriting base function or some thing else. I get confused on ":base(option) {}" it doesn't make sense
public ApplicationDbContext(DbContextOptions options)
: base(options) {}
In order to explain what is happening, first I'm going to make a few assumptions:
1) The class in which your constructor code
public ApplicationDbContext(DbContextOptions options) : base(options) {}
resides in is called "ApplicationDbContext".
2) ApplicationDbContext inherits directly from the "DbContext" class. Which makes DbContext the base class of ApplicationDbContext.
": base" means 'call the constructor of the base class when the constructor of ApplicationDbContext is called.'
": base(options)" means 'call the constructor of the base class using the passed parameter of the type DbContextOptions called "options", when the constructor of ApplicationDbContext is called.'
The ":" symbol is part of the C# syntax to specify the calling of a base method.
Related
How can I apply the :base("name=connectionstring_name") in ASP.NET Core?
Because my Visual Studio shows cannot convert from 'string' to 'Microsoft.EntityFrameworkCore.DbContextOptions' .
namespace SchoolDataLayer
{
public class Context: DbContext
{
public SchoolDBContext() : base("name=SchoolDBConnectionString")
{
}
}
}
public SchoolDBContext() : base("name=SchoolDBConnectionString")
As error says you should pass DbContextOptions class instead of connection string.
The DbContextOptions instance carries configuration information such as:
The database provider to use, typically selected by invoking a method such as UseSqlServer or UseSqlite. These extension methods require the corresponding provider package, such as Microsoft.EntityFrameworkCore.SqlServer or Microsoft.EntityFrameworkCore.Sqlite. The methods are defined in the Microsoft.EntityFrameworkCore namespace.
Any necessary connection string or identifier of the database instance, typically passed as an argument to the provider selection method mentioned above
Any provider-level optional behavior selectors, typically also chained inside the call to the provider selection method
Any general EF Core behavior selectors, typically chained after or before the provider selector method
here is an example:
public class Context: SchoolDbContext
{
public SchoolDbContext(DbContextOptions<SchoolDbContext> options)
: base(options)
{
}
}
for more information read https://learn.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext
I want to define a base configuration (for some reason) for all model configuration(which using fluent api on them), so i create BaseConfigration class:
public class BaseConfigration<T> : EntityTypeBuilder<T> where T : class
{
public BaseConfigration(InternalEntityTypeBuilder builder) :base(builder)
{
}
}
and all of other configuration inherit from it:
public class LoyaltyActivityConfig : BaseConfigration<LoyaltyActivity>
{
public LoyaltyActivityConfig(InternalEntityTypeBuilder builder) : base(builder)
{
this.Property(x => x.Title).HasMaxLength(100);
}
}
in this point all thing goes right, but when i want to introduce this configuration in OnModelCreating method:
new LoyaltyActivityConfig(modelBuilder.Entity<NotificationPlatform>());
it gives me error:
cannot convert from 'Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder' to 'Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder'
How can i do it?
As the exception message says, you are using incorrect type. During OnModelCreating you have EntityTypeBuilder<T> object. InternalEntityTypeBuilder should not be used in user code as its internal to EF core as said in documentation.
To define a BaseConfiguration which will be applied to each entity type in the model and derived by EntityTypeConfiguration, code should be organized in following manner:
public class BaseConfiguration<T> where T : class
{
public BaseConfiguration(EntityTypeBuilder<T> entityTypeBuilder)
{
// Write fluent API code here which will be applied to all entityTypes in the model
entityTypeBuilder.HasKey("Id");
}
}
public class LoyaltyActivityConfig : BaseConfiguration<LoyaltyActivity>
{
public LoyaltyActivityConfig(EntityTypeBuilder<LoyaltyActivity> entityTypeBuilder)
: base(entityTypeBuilder)
{
// Write fluent API code here which will be applied to EntityType LoyaltyActivity only
entityTypeBuilder.Property(x => x.Title).HasMaxLength(100);
}
}
Then call above code from OnModelCreating like this
new LoyaltyActivityConfig(modelBuilder.Entity<LoyaltyActivity>());
Above method will call BaseConfiguration constructor followed by EntityTypeConfiguration constructor, applying all fluent API code.
Few things to remember here,
In BaseConfiguration even if you have generic EntityTypeBuilder you will not be able to use generic methods since T is unknown type. You can define an interface which will be implemented by every T (all entity types in the model) and use generic methods afterwards. Using non-generic methods will also get you same result though. Its just matter of readability.
You can also use method calls instead of constructor in Config classes to achieve the same.
To organize code like above, IEntityTypeConfiguration<TEntity> feature from EF6 has been implemented in EF core and will be available in 2.0 release. More info https://github.com/aspnet/EntityFramework/issues/2805
I'm trying to implement a class instance of an interface class. Exploring the interface (.NET DLL) with the project explorer, it says:
bool CreateInstance(SharedLibrary::MemoryArbiter^ pntMemory,
SharedLibrary::clsMessageQueue^ pntMessageQueue,
SharedLibrary::clsGPIO^ pntGPIO,
SharedLibrary::Types^ pntProgramSettings,
SharedLibrary::DisplayDriver^ pntDisplayDriver)
Member from Plugin_Interface::IPlugin
But if I write in my MyClass.h:
using namespace System;
using namespace System::ComponentModel;
using namespace SharedLibrary;
namespace MyCppPlugin {
[AttributeUsageAttribute(AttributeTargets::Class | AttributeTargets::Method |
AttributeTargets::Property | AttributeTargets::Field,
AllowMultiple = true, Inherited = false)]
ref class MyPlugin abstract : public Plugin_Interface::IPlugin
{
bool CreateInstance(SharedLibrary::MemoryArbiter^ pntMemory,
SharedLibrary::clsMessageQueue^ pntMessageQueue,
SharedLibrary::clsGPIO^ pntGPIO, SharedLibrary::Types^
pntProgramSettings, SharedLibrary::DisplayDriver^ pntDisplayDriver);
};
};
It says: "error C3766: Missing implementation of Plugin_Interface::IPlugin::CreateInstace(...)
What the heck do I do wrong?
EDIT:
Forgot the abstract statement.
And: Why is it saying "IntelliSense: Class can not implement interface member function "Plugin_Interface::IPlugin::CreateInstance" (declared in "Plugin_Interface.dll")"
???
You got a lot more diagnostic messages from this snippet, you are making several mistakes:
[AttributeUsage] is only valid on a class that derives from System::Attribute. You no doubt need to use some kind of attribute so that the plugin host can recognize your class as a valid plugin candidate, I can't guess what that attribute might be.
A method that implements an interface method should be public.
A method that implements an interface method must be virtual.
The method signature must be an exact match with the interface method declaration.
Just in case: you must actually implement the method, not just declare it.
The third and forth bullets are the chief reasons for the "must provide an implementation of the interface method" compile error. So proper code ought to resemble something like this:
[NoIdeaWhatAttribute]
public ref class MyPlugin : public Plugin_Interface::IPlugin {
public:
virtual bool CreateInstance(SharedLibrary::MemoryArbiter^% pntMemory,
SharedLibrary::clsMessageQueue^% pntMessageQueue,
SharedLibrary::clsGPIO^% pntGPIO,
SharedLibrary::Types^% pntProgramSettings,
SharedLibrary::DisplayDriver^% pntDisplayDriver)
{
// Todo...
return false;
}
};
I got it. Thanks to Hans Passant who gave me so many hints :)
To export the function it has to implement the Interface 1:1. The export statement has to be added over the class header:
[Export(IPlugin::typeid)]
public ref class MyPlugin : public Plugin_Interface::IPlugin
And: While VB.NET will compile to "Any CPU" and C++/CLI will compile to Win64/Win32 it will missfit. Both Projects have to have the same target - either 64bit OR 32bit.
Now it works.
I am trying to switch to Simple Injector Dependency Injection framework as I am impressed with its speed.
private static void RegisterServices(Container container)
{
container.RegisterPerWebRequest<IDbContext, DbContext1>();
////container.RegisterPerWebRequest<IDbContext, DbContext2>();
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
container.RegisterPerWebRequest<IColourRepository, ColourRepository>();
where DbContext1 and DbContext2 inherit from a BaseDbContext class
public class BaseDbContext<TContext> : DbContext, IDbContext where TContext : DbContext
which implements a rather simple IDbContext interface (like the many offered on SO), e.g:
public interface IDbContext
{
IQueryable<TEntity> Find<TEntity>() where TEntity : class;
DbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
void Dispose();
}
If I use just a single DbContext class, it works fine - repositories get injected, data pulled etc.
However, I'd also like to use bounded contexts with a smaller number of DbSets in each of them (Shrink EF Models with DDD Bounded Contexts) as my Code-First DbContext would otherwise include hundreds of classes
private static void RegisterServices(Container container)
{
container.RegisterPerWebRequest<IDbContext, DbContext1>();
container.RegisterPerWebRequest<IDbContext, DbContext2>();
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
container.RegisterPerWebRequest<IColourRepository, ColourRepository>();
Then I get an exception:
System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=Type IDbContext has already been registered and the container is currently not configured to allow overriding registrations. To allow overriding the current registration, please set the Container.Options.AllowOverridingRegistrations to true.
Source=SimpleInjector
StackTrace:
at SimpleInjector.Container.ThrowWhenTypeAlreadyRegistered(Type type)
at SimpleInjector.Container.AddRegistration(Type serviceType, Registration registration)
at SimpleInjector.Container.Register[TService,TImplementation](Lifestyle lifestyle, String serviceTypeParamName, String implementationTypeParamName)
at SimpleInjector.Container.Register[TService,TImplementation](Lifestyle lifestyle)
at SimpleInjector.SimpleInjectorWebExtensions.RegisterPerWebRequest[TService,TImplementation](Container container)
If I follow the suggestion:
container.Options.AllowOverridingRegistrations = true;
then DbContext2 seems to override DbContext1, e.g. DbSet "Colour" is in DbContext1 and it is not accessible any more:
Additional information: The entity type Colour is not part of the model for the current context.
How should I use Simple Injector and bounded DbContexts together?
[UPDATE]
The DbContexts are no used in controllers directly, they are dependencies of repositories which Simple Injector should be able to initialise in constructors
public class ColoursController : ApiController
{
private readonly IColourRepository _repository;
private readonly ModelFactory _modelFactory;
public ColoursController(IColourRepository repository)
{
_repository = repository;
_modelFactory = new ModelFactory();
}
where
public class ColourRepository : Repository<Colour>, IColourRepository
{
public ColourRepository(IDbContext context) : base(context) { }
ColourRepository expects a concrete implementation of DbContext1, but some other repository would need DbContext2 (with a different set of entities)
I do not see the reason why it is impossible to use IDbContext interface (or a base type) for both DbContext1 and DbContext2.
Unity can do it:
container.RegisterType<IDbContext, NorthwindContext>(new PerRequestLifetimeManager(), "NorthwindContext");
container.RegisterType<IDbContext, NorthwindCustomerContext>(new PerRequestLifetimeManager(), "NorthwindCustomerContext");
Ninject can do it.
Simple Injector mentions CompositeLogger - maybe that one could do the trick?
https://simpleinjector.org/
ColourRepository expects a concrete implementation of DbContext1, but
some other repository would need DbContext2 (with a different set of
entities)
Your design is currently ambiguous. Although your design speaks about an IDbContext and it looks like if there's just one abstraction with two implementations, but those implementations are not interchangeable (a Liskov Substitution principle violation) which is an indication that there should in fact be two different interfaces. Besides, having one single interface makes your DI configuration more complicated and harder to maintain (this is independent on the framework you pick).
So the solution is to remove the ambiguity from your design by giving each context its own interface. This allows your repositories to take the dependency on the abstraction they need:
public class ColourRepository : Repository<Colour>, IColourRepository
{
public ColourRepository(ICustomerDbContext context) : base(context) { }
}
And this allows you to simplify the registration:
container.Register<IDbContext, NorthwindContext>(Lifestyle.Scoped);
container.Register<ICustomerDbContext, NorthwindCustomerContext>(Lifestyle.Scoped);
Note that using keyed registrations won't solve the core problem; you'll still forced to explicitly state which keyed version should be injected in which repository, which will make your DI configuration a maintenance nightmare and very error prone.
I'm trying to implement a repository solution for Entity Framework but I am having trouble registering the types that include generics using Unity.
Given:
// IRepository interface
public interface IRepository<TEntity>
{
// omitted for brevity
}
// Repository implementation
public class Repository<TEntity, TContext> : IRepository<TEntity>, IDisposable
where TEntity : class
where TContext : DbContext
{
// omitted for brevity
}
// service layer constructor
public MyServiceConstructor(IRepository<Account> repository)
{
_repository = repository;
}
I need to register the type mapping for IRepository to Repository. but I'm having trouble with the Unity syntax for this kind of mapping.
I have tried the following with no luck:
container.RegisterType<IRepository<>, typeof(Repository<,>)>();
container.RegisterType<typeof(IRepository<>), Repository<,>>();
EDIT
Based, on #Steven response I have the following implementation now:
// UnityRepository implementation
public class UnityRepository<TEntity> : Repository<TEntity, MyDbContextEntities>
where TEntity : class
{
public UnityRepository() : base(new MyDbContextEntities()) { }
}
// Unity bootstrapper
container.RegisterType(typeof(IRepository<>), typeof(UnityRepository<>));
You are trying to do the following:
container.RegisterType(typeof(IRepository<>), typeof(Repository<,>));
This would normally work, but won't do the trick in this case, since there is IRepository<TEntity> has one generic argument and Repository<TEntity, TContext> has two, and Unity (obviously) can't guess what type it should fill in for TContext.
What you need is this:
container.RegisterType(
typeof(IRepository<>),
typeof(Repository<, MyDbContextEntities>));
In other words, you'd want to supply the Repository<TEntity, TContext> as a partial open generic type (with one parameter filled in). Unfortunately, the C# compiler does not support this.
But even if the C# did support this, Unity doesn't support partial open generic types. In fact most IoC libraries eworks don't support this. And for that one library that does support it, you would still have to do the following (nasty thing) to create the partial open generic type:
Type myDbContextEntitiesRepositoryType =
typeof(Repository<,>).MakeGenericType(
typeof(Repository<,>).GetGenericParameters().First(),
typeof(MyDbContextEntities));
There's a easy trick work around to get this to work though: define a derived class with one generic type:
// Special implementation inside your Composition Root
public class UnityRepository<TEntity> : Repository<TEntity, MyDbContextEntities>
where TEntity : class
{
public UnityRepository([dependencies]) : base([dependencies]) { }
}
Now we can easily register this open generic type:
container.RegisterType(typeof(IRepository<>), typeof(UnityRepository<>));