This question already has answers here:
Implementing Repository pattern and doing Tests
(2 answers)
Closed 8 years ago.
I'm creating a new web application based on ASP.NET Web API and EF6.
ProjectName
-ProjectName.Data (All entity framework stuff)
-ProjectName.Service (All business logic)
-ProjectName.Web (ASP.NET Web API All front end logic)
I've read tons of information the repository pattern & UoW , and the vast array of options on its advantages or disadvantages with EF. (StackOverflow has 10,081 results for "repository pattern").
We have no plans EVER
to change to a different database and with EF6 i've read you can do Unit testing without additional abstraction.
I'm tending toward NOT using repository or UoW and instead talking directly to DbContext from the service layer.
Can anyone provide examples that implement EF6 without a repository, with a service layer ?
Even better a sample project or github project using this in real life ?
Edit:
Similar Questions:
Implementing Repository pattern and doing Tests
Generic Repository With EF 4.1 what is the point
these are question on the same subject but none of them provide good code example of using EF in a architecture similar to the one i described:
How to manage DbContext lifetime without repository / UoW?
How to implement unit testing using ef6 new features ?
Your question is too broad. There are too many ways to achieve the same result. Here is my two cents -
Although you do not want to use Repository, you still want to inject Dependencies using IoC container such as Ninject, Autofac and StructureMap.
If so, you just need to inject YourDbContext to Service class.
For example,
public class CustomerService : ICustomerService
{
private readonly YourDbContext _context;
private readonly ICacheService _cacheService;
...
public StateService(
YourDbContext context,
ICacheService cacheService,
...)
{
_context = context;
_cacheService = cacheService;
...
}
}
Related
In a nutshell I'm in the process of upgrading a .NETStandard 2.1 app to .NET 6. Plus upgrading the various libraries accordingly, in particular MassTransit v5 to v8, and AutoFac 4.9.4 to 6.4.0.
This is a multi-tenant application where one instance is shared by multiple tenants, and each tenant has their own database.
The upgrade has gone well apart from one snag. The application uses the, no longer available, AutofacReceivedEndpointExtensions to setup the Tenant details in the Consumer, and I am struggling to find a way to replicate the functionally it provides.
Below is the key bit of code.
config.ReceiveEndpoint(host, azureBusConfig.QueueName, endpoint =>
{
ConfigureConsumer<MyConsumer>(endpoint, componentContext);
});
private static void ConfigureConsumer<TConsumer>(IServiceBusReceiveEndpointConfigurator endpoint, IComponentContext componentContext, Action<IConsumerConfigurator<TConsumer>> configure = null)
where TConsumer : class, IConsumer
{
endpoint.Consumer(componentContext, configure, configureScope: (container, context) =>
{
var tenantName = context.Headers.Get<string>("tenant");
var userId = context.Headers.Get<int>("userId");
container.RegisterInstance(new NamedTenantInfoProvider(tenantName, userId)).As<ITenantInfoProvider>();
});
}
The endpoint.Consumer method as shown is no longer provided.
The ITenantInfoProvider interface is injected into various constructors in the application e.g., to setup the dbContext for a tenant to point to the correct database.
public interface ITenantInfoProvider
{
string GetTenantName();
int? GetUserId();
}
There are two implementations of the ITenantInfoProvider. The NamedTenantInfoProvider which is used to set the Tenant from the received message, above.
There is also a RequestTenantInfoProvider, that gets the Tenant from the HttpRequest. e.g. via api call.
The RequestTenantInfoProvider is registered as follows
builder.RegisterType<RequestTenantInfoProvider>()
.As<ITenantInfoProvider>()
.InstancePerLifetimeScope();
So, what should happen is that the RequestTenantInfoProvider is injected into the constructors by default, but when a message is being consumed the NamedTenantInfoProvider instance is injected instead.
I have tried to register the NamedTenantInfoProvider as per the RequestTenantInfoProvider. Then inject an IEnumerable into the constructors. And set the Tenant in the consumer.ConfigureConsumer on the Named instance. Then use which ever instance has a Tenant set in the code. However, the NamedTenantInfoProvider instance is set after it is required in the other constructors e.g., dbContext.
The only way I can get the application to fully work is to hardcode a Tenant name in the NamedTenentInfoProvider class.
I was hoping that someone has already refactored some similiar code to replace the endpoint.ConfigureConsumer call and can advise a solution.
It may be that I'm missing a bit of knowledge regarding how scoping works with the Microsoft Dependency Injection/MassTransit configuration. Note: I didn't write the original application, and this is my first dabble with Mass Transit as well.
MassTransit v8 (and onward) only support IServiceCollection, which is part of Microsoft.Extensions.DependencyInjection. Third-party containers are no longer directly supported.
There is a Scoped Filter sample that might help you understand how scopes work with MSDI. The token concept is similar to that used by developers injecting "tenant info" into consumers.
Is there a way to create an IDbContext interface for DI (using AutoFac)?
i am using asp.net mvc 5 & EF 6.
and i would like to create an Interface for Dependency Injection.
There is some way to do it?
Currently i am register my Context class and it will work fine
builder.RegisterType<CustomContext>().SingleInstance().InstancePerLifeTimeScope();
DbContext's should be short-lived. A common pattern for working with EF Contexts is the Unit of Work pattern. There are a few out there for EF that can help manage the scope of a DbContext. At worst for ASP.Net you would want the DbContext lifetime set to the Request, no longer.
Option 1: (Recommended) Register a unit of work implementation (Such as Medhime's DbContextScope) and let that manage the DbContext scope. These follow the Interface/Concrete definitions to work well with DI.
Option 2: Register a DbContextFactory and use that to provide DbContexts. I.e.
using (var context = ContextFactory.Create())
{
// ....
}
Where ContextFactory is a defined DbContextFactory class implementing an IDbContextFactory interface.
Option 3: Register the DbContext itself as a PerRequest lifetime scope.
If your goal is to inject DbContexts to facilitate testing, I would highly recommend adopting a Repository pattern (Not a Generic Repository pattern I.e. Repository<TEntity>) and utilizing either Option 1 or Option 2. The advantage of a repository is that it serves as a boundary for the unit tests. Your "code under test" can then be served a Mocked repository class which in turn returns stubbed entities or IEnumerable<TEntity>/IQueryable<TEntity>. Mocking DbContexts and their DbSets is honestly a PITA. Repository methods can be tested if & as desired using integration-style tests talking to a real database.
I'd like to start a WPF app using .NET Core 3.1
Can Prism make use of .Net Core's built-in DI (IServiceCollection) or do I have to use something like Unity?
If Prism cannot use the built-in DI, can they exist side-by-side?
Can Prism make use of .Net Core's built-in DI
From what I've seen you can't really replace Prism's DryIot with the ASP.NET Core build-in one. Mainly DryIot is more feature-full than the ServiceCollection API. There is this opensource package I've found that has an IContainerExtension implementation using ServiceCollection, but per the developer's own words this is more of a proof of concept rather than sable solution.
If Prism cannot use the built-in DI, can they exist side-by-side?
Yes, they can. With a caveat - you cannot simply register a service in ServiceCollection and expect to be able to inject that service directly in your App, Modules and ViewModels. This will fail because those files are managed by the Prism framework and thus injection will only work for services you have registered using the IContainerRegistry interface.
Benefits
Why would you do it? As the build-in IoT container the ServiceCollection API is well-known, thus it will be simpler for .Net developers. Furthermore you can structure you non-WPF projects to register services using the default container thus allowing them to be completely decoupled from your Desktop project. This is very good for more complex architectures like Domain-Driven Design.
Let's consider the following project structure:
solution
-- Desktop // Prism WPF application, containing only views and models
-- Application // Class library, containing operational logic.
Let's say that as a part of the Application project you need an IUserService which holds information about the current user that has to be populated in-memory when the user authenticates in the Desktop app. A registration method would look like this:
public IServiceCollection AddServices(this IServiceCollection services)
{
services.AddSingleton<IUserService, UserService>()
}
So now we need to inject it inside the Desktop project. I suggest two methods:
Simple
Seemless
Simple
This approach requires very simple startup configuration. The caveat is that you will not be able to inject your services directly in the constructor, but through the IServiceProvider interface.
Reference Microsoft.Extensions.DependencyInjection
Call your service registration method in App:
protected override void RegisterTypes(IContainerRegistry container)
{
// Build service provider using the ServiceCollection API
var provider = new ServiceCollection()
.AddServices()
.BuildServiceProvider();
// Register IServiceProvider within DryIot and provide
// a factory method to retrieve the service instance
container.Register<IServiceProvider>(() => provider);
}
Inject IServiceProvider where you need IUserService. For this example I'll use a Prism Module:
public class Module : IModule
{
private readonly IUserService userService;
public Module(IServiceProvider serviceProvider)
{
this.userService = serviceProvider.GetService<IUserService>();
}
...
private void Authenticate()
{
this.userService.IsAuthenticated = true;
}
}
That's it, you can now use your ServiceCollection registered dependency wherever you can access the IServiceProvider through Prism injection. This is the approach I recommend, because we are simply wrapping the .Net container in Prism's.
Seemless
This is where it gets a bit more interesting. Full disclaimer - you might encounter problems using this approach. I have not yet tested this beyond the most basic use-case. The only advantage this method offers is that you will be able to directly inject services in the constructor, instead of having to go through the IServiceProvider.
In its essence this method is simply looping through the ServiceCollection and registering all services directly in the Prism container. If we take a look at the implementation of ServiceCollection - it is simply a list of ServiceDescriptors. Upon further inspection we observe that ServiceDescriptior contains a bunch of constructors. We'll ignore those and focus on the properties:
ServiceType - the type that will be used when injecting
ImplementationType - type of the implementation to be injected
ImplementationInstance - instance of the implementation type
ImplementationFactory - factory delegate that returns an instance of the implementation type
LifeTime - Singleton, Scoped or Transient type
Let's now inspect the IContainerRegistry interface. We'll see that there are a lot of overloads of Register that accept Types, object and delegates.
Using that knowledge we can now create an adapter from ServiceDescriptor to registration of IContainerRegistry. The below implementation will only focus on Transient services, but the difference between service lifetimes is simply which registry method we call - Register for a Transient and RegisterSingleton for well Singletons.
Create and Adapter class with static method that accepts IContainerRegistry and ServiceDescriptor arguments:
public static void Register(IContainerRegistry container, ServiceDescriptor service)
{
// In case an implementation instance is provided we simply need to register it
if (service.ImplementationInstance != null)
{
containter.Register(service.ServiceType, service.ImplementationInstance);
}
// In case a factory is provided we have a bit more work.
// We need to modify it in order for it to be usable by the DryIot container
else if (service.ImlementationFactory != null)
{
var factory = service.ImplementationFactory;
var dryIotFactory = dryIotProvider =>
{
var provider = dryIotProvider.Resolve<IServiceProvider>();
return factory(provider);
};
container.Register(service.ServiceType, dryIotFactory);
}
// If no implementation or factory is provided then we simply register the
// types and let the container create the implementation instance on its own.
else
{
container.Register(service.ServiceType, service.ImplementationType);
}
}
The most tricky part here is the factory. To better understand factories in service-registration know that sometimes you may need access to other services to provide the correct implementation instance. For example if IHttpClient is registered you need to provide the IAuthorizationSerice with HttpAuthorizationService implementation instead of DesktopAuthorizationService.
Essentially we wrap the original factory method with a DryIot-compatible factory (accepts instance of DryIot container) that can supply the original factory with IServiceProvider instance.
Reference Microsoft.Extensions.DependencyInjection
Call your service registration method in App:
protected override void RegisterTypes(IContainerRegistry container)
{
var services = new ServiceCollection().AddServices()
foreach (var service in services)
{
Adapter.Register(container, service);
}
}
Inject IUserService directly in the module constructor:
public class Module : IModule
{
private readonly IUserService userService;
public Module(IUserService userService)
{
this.userService = userService;
}
}
Final thoughts
Again, I recommend the simple approach. Simplicity means lower learning curve and less room for errors. The inconvenience is minor in comparison.
Another fair warning - this is not production ready code. Especially the seemless method. I have yet to "battle-test" this implementation, but it might point you in the right direction.
If anyone has feedback/opinions I would be glad to read about it :)
Can Prism make use of .Net Core's built-in DI
Short Answer, NO
Here is a comment by #brianlagunas (The creator of Prism)
As I mentioned, we can't use IServiceProvider as we are in netstandard 1.0. The ServiceProvider and IServiceCollection is in netstandard 2.0. Also, there are a number of features that Prism needs that are to limited in the IServiceCollection implementation. Such as named instances and registrations, as well as a mutable container.
here is a comment by #dansiegel
I have spent a lot of time discussing this issue, and ultimately we cannot directly rely on IServiceProvider and IServiceCollection for a variety of reasons that extend beyond whether or not they are available.
here is the another comment also by
#brianlagunas
do I have to use something like Unity?
The ServiceCollection is "something like Unity". And, yes, you can use it with prism:
Create an IContainerExtension implementation that redirects to ServiceCollection
Derive from PrismApplicationBase and return your container extension from CreateContainerExtension
We are using forms authentication on our ASP.NET website but are wanting to upgrade to the new Identity Provider. Currently we are using the database first approach and are ultimately wanting to just extend our current User table (not aspnet_users) to use the new identity format. We are using StructureMap to inject our context into our business logic classes. For instance our User service currently has this as its constructor:
private readonly SiteModelContainer _context;
public UserService(SiteModelContainer context)
{
this._context = context;
}
And in our IoC registry we have this:
var ecsbuilder = new EntityConnectionStringBuilder();
ecsbuilder.Provider = "System.Data.SqlClient";
ecsbuilder.ProviderConnectionString = #"data source=***;initial catalog=***;persist security info=True;User ID=***;Password=***;multipleactiveresultsets=True;App=EntityFramework";
ecsbuilder.Metadata = #"res://*/Data.***.csdl|res://*/Data.***.ssdl|res://*/Data.***.msl";
string connectionString = ecsbuilder.ToString();
For<SiteModelContainer>().Use<SiteModelContainer>().Ctor<string>("connectionString").Is(connectionString);
For<IUserService>().Use<UserService>();
...all the rest of our services
We are also using database first with EDMX and entity framework. Previously we just used ASP.NET authentication as it came out the box and had a separate user table to store profile information, but would like to have everything working off one users class instead.
1)Is it possible to extend our userservice to handle everything related to using Identity? So that Identity uses the same context that we inject into our classes? If so, I am unable to find any articles about it?
2) Are we able to extend our User object if it is created in the EDMX file?
Thanks
I have migrated 2 fairly large projects from MembershipProvider into Asp.Net Identity and both of the times I ended up rewriting most parts of the user-management and everything that touched user. A fairly chunky rewrites.
What you ask for is possible, but hard and very time consuming. You may start from this question - the OP have got his db-first project running with identity. And we had a discussion in comments with some links that might help you.
I have used UnitOfWork and Repository patterns in my application with EF.
Actually my design provides that the UnitOfWork would create the ObjectContext class and inject inside the Repository concrete class. For example:
UnitOfWork.cs (initialization)
public DefaultUnitOfWork() {
if (_context == null) {
_context = new MyDataContext(ConfigSingleton.GetInstance().ConnectionString);
}
}
UnitOfWork.cs (getting a repository instance)
public CustomerRepository Customers {
get {
if (_customers == null) {
_customers = new CustomerRepository(_context);
}
return _customers;
}
}
This way the Repository classes have an already defined ObjectContext class and they can use it's methods to retrieve and update data.
This works nice.
Now I need to execute my queries impersonating the Application Pool Identity so I have decided to wrap the code in the constructor of the UnitOfWork within the impersonation.
Unfortunately this does not work because the ObjectContext is then passed to the Repository constructor and used later when a client of the repository calls, for example, FindAll().
I have experienced that the real connection to the database is made right before doing the query by Entity Framework and not exactly when I am creating the ObjectContext itself.
How can I solve this problem?
You could use one or more ObjectContext Factories (to create ObjectContexts), using different creation criteria, such as Connection String, for example. Your UnitOfWork could leverage a factory to get its Context and so could the Repository, but I think you've missed the point of UnitOfWork if it is leveraging a different ObjectContext than your Repository.
A UnitOfWork should consist of one or more operations that should be completed together, which could easily leverage multiple repositories. If the repositories have their own ObjectContexts separate from the UnitOfWork, I don't see how committing the UnitOfWork will achieve it's purpose.
I think either I've misinterpreted your question completely or you've left out some pertinent details. Good Luck!