Adding service for EF, AddDbContext or AddEntityFramework - asp.net-core

Is there a difference between services.AddDbContext and services.AddEntityFramework().AddDbContext? They booth looks to be valid under core-1.0.0.
Choice A
services.AddDbContext<DbContext>(options => options.UseSqlServer(connection));
Choice B
services.AddEntityFramework()
.AddDbContext<DbContext>(options =>
options.UseSqlServer(connection));
Also noticed that .AddSqlServer() looks to be gone. Last time I did some work on core was RC2 and I see that a lot has been cleaned/renamed/simplified, I guess that's nice.

I'm quoting: You only need to use this functionality (AddEntityFramework) when you want Entity Framework to resolve the services it uses from an external IServiceProvider.
If you are not using an external IServiceProvider, Entity Framework will take care of creating the services it requires.
See: https://github.com/aspnet/EntityFramework/blob/dev/src/Microsoft.EntityFrameworkCore/Infrastructure/EntityFrameworkServiceCollectionExtensions.cs
I'm quoting: Intentionally in this namespace since this is for use by other relational providers rather than by top-level app developers.
See: https://github.com/aspnet/EntityFramework/blob/94138e66a56693395e5e323a8d4b666bbcb07bf7/src/Microsoft.EntityFrameworkCore/Infrastructure/EntityFrameworkServiceCollectionExtensions.cs

Related

What is the difference between AddAuthentication and AddAuthenticationCore?

Looking at the code for AuthenticationServiceCollectionExtensions.AddAuthentication() vs AuthenticationCoreServiceCollectionExtensions.AddAuthenticationCore(), it looks like AddAuthentication implicitly calls AddAuthenticationCore, adds some other goodies, and then returns a new instance of AuthenticationBuilder instead of just returning IServiceCollection.
Am I understanding the code correctly? If so, are there generally any reasons to call AddAuthenticationCore instead of AddAuthentication outside of writing your own extension?
It seems to be a typical pattern in ASP.NET Core: the Add[xxx]Core methods add the bare minimum to enable a feature, but without any bells and whistles. It's also probably used to make unit testing the core features easier.
You can make a parallel with the AddMvc vs AddMvcCore methods. There's a question that asks Should I use AddMvc or AddMvcCore for ASP.NET Core MVC development?, and the gist is that it allows for fine-grained control on what middleware you want to use.
To answer your question: for a typical user, there's probably no reason to use AddAuthenticationCore.
Actually there is a reason. Currently AddAuthentication() also adds data protection services, which you may not need - for example if you are writing your own Authentication Scheme. So instead you can do this:
services.AddAuthenticationCore(o => {
o.DefaultScheme = "My Custom Scheme";
});
services.AddWebEncoders();
services.AddSingleton<ISystemClock, SystemClock>();
var authBuilder = new AuthenticationBuilder(services);
however I fully expect this to break in future versions of asp.net core as it's undocumented and a bit of a hack.

How do I auto-register/resolve services by their interface?

I'm developing a MVC .NET Core 3/Angular/Entity Framework application. My application will likely have a lot of repositories in it. To support this I would like to resolve the service (repository) by its default interface (i.e. I request IRepository and the DI resolver gives me Repository). I know I can manually wire up the dependencies, but all of my DI frameworks in the past have had a means of auto-registering/resolving based on patterns or the like.
For example, with Castle Winsdor I could wire it up like this:
container.Register(Classes
.FromAssemblyNamed("MyLibary.Repository")
.InNamespace("MyLibrary.Repository")
.WithService.DefaultInterfaces()
.LifestyleTransient()
);
This would register all classes in the MyLibrary.Repository namespace to be resolved by their default interfaces they implement. How can this be done in .NET Core 3? If this isn't built-in, I'm assuming I will have to use reflection to query all the classes in the assembly, iterate through each class and register it by its interface it implements.
I would recommend AutoRegisterDI lib to not reinvent a bicycle. It's fast, simple and based on Microsoft Dependency Injection. This benchmark will show you the speed difference.
And this is the article about how to use it
Install this package:
NetCore.AutoRegisterDi
Add this code to your program.cs:
builder.Services.RegisterAssemblyPublicNonGenericClasses()
.Where(c => c.Name.EndsWith("Service"))
.AsPublicImplementedInterfaces(ServiceLifetime.Scoped); // default is Transient
If you have a Singleton service , add [RegisterAsSingleton] on top of your service class.
If you want to ignore injection of an particular interface add this line after .Where() :
.IgnoreThisInterface<IMyInterface>()
you can do this with reflection in c#.first create an extension method like this :
public static void AddScopedServices(this IServiceCollection serviceCollection)
{
}
and use it in startup.cs ,ConfigureServices method : services.AddScopedServices();
now to implement this method like this:
var allProviderTypes = System.Reflection.Assembly.GetAssembly(typeof(ICartRepository))
.GetTypes().Where(t => t.Namespace != null).ToList();
foreach (var intfc in allProviderTypes.Where(t => t.IsInterface))
{
var impl = allProviderTypes.FirstOrDefault(c => c.IsClass && intfc.Name.Substring(1) == c.Name);
if (impl != null) serviceCollection.AddScoped(intfc, impl);
}
you just need to put all your interfaces in a namespace and introduce one of them in this method ,in my case I used ICartRepository ,so it takes all interfaces and search for classes which inherit from that interface.
one point you need to consider is that class names must be like interfacenames without 'I' in the beginning ,like 'CartRepository'
I recently got tired of writing the same old
services.AddTransient<IInterface,IImplementation>
so I created a simple library to help me auto-register services.
You can check it out here.
Register the library in Startup.cs
There are 3 interface -> ITransient, IScoped, ISingleton generic and non-generic versions.
Let's say you want to register service "TestService" as transient.
TestService: ITransient<ITestService>, ITestService
Inherit ITransient interface and its done.
For more detailed information please refer to the Readme section.
Currently it lacks registering services with implementation factory, but it's something I'm willing to do in the near future.

Where is .AddDbContext method?

Everywhere it's said to call services.AddDbContext<> method but it is not recognized inside the ConfigureServices(IServiceCollection services) method.
What am I doing wrong?
You have to reference the correct package first, which depends on the EF Core provider you want to use.
Microsoft.EntityFrameworkCore.SqlServer for SQL Server, Microsoft.EntityFrameworkCore.Sqlite for SQLite and Microsoft.EntityFrameworkCore.InMemory for in memory (only for testing).
These are the official out-of-the-box providers. There are also 3rd party providers for PostgreSQL, MySQL, etc. The documentation providers a list of available 3rd party providers here.
Also depending on the provider you may also need to declare a certain namespace. The built-in providers are declared in Microsoft.Extension.DependencyInjection namespace so you need to add a using Microsoft.Extension.DependencyInjection; to the top of your Startup.cs.
Other providers (Oracle's MySQL provider for example) uses MySQL.Data.EntityFrameworkCore.Extensions namespace, so you need to define this using using MySQL.Data.EntityFrameworkCore.Extensions;
Note when actually writing the using you only have to reference Microsoft.EntityFrameworkCore omitting the specific package name. Providing it seems to throw an error.

How to register EF DbContext with NetTcpBinding WCF using DI (Castle Windsor WCFFacility)?

I'm using EF6 CodeFirst and WCF 4.5 with NetTcpBinding and BasicHttpBinding. Also I'm using Castle.Windsor for DI.
I have the following architecture:
MySolution.Core (class library)
- Domain
-- (...domain classes...)
- Data
-- IRepository.cs
MySolution.BusinessLogic (class library)
- (...business logic classes...)
MySolution.Data (class library using EF6)
- Models
-- Mapping
-- MyContext.cs (MyContext : DbContext, IDbContext)
- EFRepository.cs (EFRepository : IRepository, where in constructor is injected IDbContext)
- IDbContext.cs
MySolution.Services (WCF Project hosted in IIS with http and net.tcp)
- AppCode
-- Initialization.cs (instead global.asax, to be used with netTcpBinding)
- Installers
-- BusinessLogicInstaller.cs
-- RepositoriesInstaller.cs
-- ServicesInstaller.cs
In AppCode/Initialization.cs I have:
container = new WindsorContainer();
container.AddFacility<WcfFacility>();
container.Install(
new ServicesInstaller(),
new BusinessLogicInstaller(),
new RepositoriesInstaller());
And, inside Installers/RepositoriesInstaller.cs:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
// registration for EF context
container.Register(Classes.FromAssemblyNamed("MySolution.Data")
.InNamespace("MySolution.Data.Models")
.WithService.AllInterfaces()
.LifestylePerWcfOperation());
// registration for EF repository classes
container.Register(Classes.FromAssemblyNamed("MySolution.Data")
.InNamespace("MySolution.Data")
.WithService.AllInterfaces()
.LifestyleTransient());
}
ServicesInstaller and BusinessLogicInstaller register classes with LifestyleTransient.
Obs: The WCF must offer RESTful binding in the future.
My questions are:
If I use netTcpBinding, I cannot use LifestylePerWebRequest for DbContext, right?
It's safe and correct to use LifestylePerWcfOperation for the DbContext? If yes, is OK to use with BasicHttpBinding also? I don't find information explaining in detail the PerWcfOperation.
Is my architecture OK? Maybe I misunderstand some important concept with IoC/DI?
Thanks!
Correct. In WCF, LifestylePerWebRequest only works for HTTP bindings where you have AspNetCompatibility enabled.
LifestylePerWcfOperation can be used with any WCF bindings.
Architecture looks pretty complex but whether it's OK or not depends on the scale and complexity of your application. Really impossible to answer that question sensibly without a ton more information. This sort of architecture is very decoupled and my first questions is whether it's over-engineered for the problem at hand and whether you're also at risk of having anemic domain model.

MVC4, UnitOfWork + DI, and SimpleAuthentication .. how to decouple?

I'm currently working on an MVC4 project, i make use if Ninject to inject a UnitOfWork into my controllers, and I'm using UnitOfWork + Generic Repository pattern.
I don't like VS2012 MVC4 template because it directly uses database access (db initialization, for example).
My project divides in:
a UI project (the mvc4 application), with Forms Authentication
a Domain project (the db entities, the repositories, the UnitOfWork interface plus two UnifOfWork implementations, one with MOQ and one with EF; they are injected into UI controllers via Ninject).
I looked at this example:
http://kevin-junghans.blogspot.it/2013/03/decoupling-simplemembership-from-your.html
related to this question
SimpleMembership - anyone made it n-tier friendly?
And now I have some question:
How can i inject my UoW here? WebSecurity class is static, there is no contructor, it directly instantiate the UoW to perform activities on db ...
I always have to initialize WebMatrix to directly access DB? This piece of code:
public static void Register()
{
Database.SetInitializer<SecurityContext>(new InitSecurityDb());
SecurityContext context = new SecurityContext();
context.Database.Initialize(true);
if (!WebMatrix.WebData.WebSecurity.Initialized)
WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection("DefaultConnection",
"UserProfile", "UserId", "UserName", autoCreateTables: true);
}
breaks my decoupling with the Domain .. how can i make WebSecurity using my UnitOfWork for example? what is the best practice?
How can i store additional data (for example, EmailAddress and so on) and retrieve it, without performing a Database query everytime i have to access the User profile? Something like the old CustomPrincipal ... Custom principal in ASP.NET MVC
Thank you!
You have a lot of questions here Marco. Let me take a stab at them.
How to inject a UOW
Static classes and dependency injection do not mix well, as pointed out in this QA. When I first went through this exercise of decoupling SimpleMembership the concentration was just on decoupling from the domain, as discussed in the article you referenced. It was just a first step and it can be improved on, including making it easier for dependency injection. I debated whether to make WebSecurity static or not and went with static because that is how the original SimpleMembership is implemented, making it a more seamless transition for user of the SimpleSecurity. SimpleSecurity is an open source project and contributions are welcome. Making it non-static would not be difficult and probably makes sense in the long run. Once it is made non-static we could use a Factory pattern to create the UnitOfWork and inject the appropriate Factory.
Why do I have to Register WebSecurity?
SimpleSecurity is just a wrapper around the WebMatrix WebSecurity classes, which require initialization. The Register method just makes sure that WebMatrix is initialized and initializes our database. I disagree that having this method call in the Globa.asax couples it with the Domain in any way. Having it work with your UnitOfWork should have nothing to do with the Application Domain, or with having to call a Register method at application start-up.
How can I store additional data (ex: email) and retrieve it, without performing a database query every time?
This is actually accomplished quite easy in .NET 4.5 by using ClaimsPrincipal. All principals in .NET 4.5 inherit from ClaimsPrincipal, which allows you to store information in the principal as claims. Claims are basically key value pairs that let you store any type of data on the user. For example in ASP.NET the roles for a user are stored as claims. To add your own claims you need to do something called claims transformation. Then to retrieve the information you can create a custom claims principal. Adding this to SimpleSecurity would be a nice feature.