EF 4.3 Context without repository - c#

I'd like to use EF directly in a business / service layer without using repositories but wondered where the best place to create / dispose the context if I want to make the class testable using a test DB?
Should it be using DI in the service constructor and mark the class as IDisposable and get rid of it there or just wrap each call in a using block?

I'm not sure on your reluctance on a repository class, but this is where I've been creating a destroying the EF context for my service layer.
So for my MVC web app, I register the repository using Autofac with lifetimescope
builder
.RegisterType<AccountRepository>()
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
My account service will get a reference to a repository instance from the container and will have access to a single context throughout the life time of the web request. Once the request is finished, Autofac will call dispose on the repository and clean up the context.
public sealed class AccountRepository : IAccountRepository, IDisposable
{
private AccountContext _context = new AccountContext();
public IList<AccountEntity> GetAccounts()
{
return _context.Accounts
.OrderBy(x => x.Name)
.ToList();
}
public void Dispose()
{
_context.Dispose();
_context = null;
}
}

Related

What is the best way to access DbContext inside a Dialog class

I have defined my DbContext in the Startup.cs
services.AddDbContext<GretaDBContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
I want to access the DbContext in my Dialogs in order to Add and Modify the entities in my database. The problem is my Dialogs are a Singleton service while the DbContext is Scoped so i can't DI it through the constructor.
I've read somewhere I should create a Controller obtaining the DbContext through the IServiceProvider and call Controller functions from the Dialogs but I don't know how to accomplish that.
What is the best way to be able to use the DbContext inside the Dialogs?
You can request a scoped service within a singleton by creating scope and then retrieving the service from an IServiceProvider that is injected into the singleton:
public class DialogsSingleton
{
private readonly IServiceProvider services;
public DialogsSingleton(IServiceProvider services)
{
this.services = services;
}
public void DomeSomethingRequiringDbContext()
{
using (var scope = this.services.CreateScope())
{
var scopedService = scope.ServiceProvider.GetRequiredService<GretaDBContext>();
// Use the scoped service
}
}
}
You should probably create a business logic layer(BLL). You can inject your DbContext into this layer. From there you should be able to inject you BLL into a controller and have your Dialogs reach out. Your controller typically shouldn't contain logic. You may be able to access your BLL from within your dialogs rather than a separate controller.

When dispose a dbcontext in .net core?

im making a project with a persistence layer, domain layer, and business layer, i implementing the generic repository pattern and unit of work with entity framework core.
I want to use this project in a web api rest and in a UWP project.
The correct ways its override the method?, add the context in the startup configureservices? When dispose a dbcontext?
Read documentation on configuring DbContext: https://learn.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext
Basically, you add it to your services:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(options => options.UseSqlite("Data Source=blog.db"));
}
Then you inject it into whatever class you want. An easy example would be inejecting it into a Controller (but you could inject into any class that is added to your services):
public class MyController
{
private readonly BloggingContext _context;
public MyController(BloggingContext context)
{
_context = context;
}
...
}
The Dependency Injection library will then handle disposal - you do not call Dispose directly. This is described in documentation here.
The framework takes on the responsibility of creating an instance of
the dependency and disposing of it when it's no longer needed.

ASP.NET Identity2 and DataContext Injecting

I have a multi tier web application working on ASP.NET MVC 5.
I have completely separated Infrastructure (DAL) from UI using a business layer.
any time UI function needs a DAL access, it calls my business service and the business service does it's job and if needed returns a result.
For IoC, Business services are injected into UI project and Infrastructure injected into Business service using Ninject
I need my UI project to have exactly 0 reference to my infrastructure project, but when it comes to using ASP.NET Identity 2 framework, It needs reference to infrastructure for ApplicationDbContext.
There are two reference to my Infrastructure project one from IdentityConfig.cs in
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
and another from Startup.Auth.cs in
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
what is the solution for this?
This is the schema of the Architecture I used:
Interfaces and factory methods will solve your problem. Whenever you want to create object - use simple factory that returns an interface of your object. And whenever you want to abstract from concrete implementation - use interfaces.
public class ApplicationDbContextFactory
{
public static IApplicationDbContext Create(IOwinContext owinContext)
{
return ApplicationDbContext.Create(owinContext);
}
}
With big thanks to #Andrei M for his great help and guidance,
I Solved this as below:
First Step: I Created An IDbContext Interface in my Domain Layer. (because from presentation we don't have access to my Infrastructure Layer)
public interface IDbContext : IDisposable
{
}
Second Step: Implement IDbContext Interface in my ApplicationDbContext in Infrastructure Layer.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDbContext
Third Step: As In my Project, the only layer that has reference to my Infrastructure Layer, is Business layer. so for use my ApplicationDbContext in my owin startup class in presentation layer, I need a Factory class in my business layer to return me a Db Context.
public static class DbContextFactory
{
public static IDbContext Create()
{
return new ApplicationDbContext();
}
}
Forth Step: Changing the Owin Startup class to use My DbContextFactory Class whenever it needs a DbContext.
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(DbContextFactory.Create);
Final Step: the only thing that remains is to change IdentityConfig.cs to don't reference directly to ApplicationDbContext in it's create method.
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var myUserStore = new UserStore<ApplicationUser>((IdentityDbContext<ApplicationUser>) context.Get<IDbContext>());
var manager = new ApplicationUserManager(myUserStore);
Actually for this step I have two solution, first is what you see above (Cast to IdentityDbContext<ApplicationUser>)
second is Cast to DbContext. I Don't know if I'll have any problem with casting to DbContext (in System.Data.Entity namespace) later, and for now I use the first solution for this.

Using dependency injection with WCF service method and EF

I am trying to get Unity dependency injection working with a WCF service that utilises Entity Framework, but I'm getting confused about the use of context and repository.
The way I have designed it is to have a number of repository classes eg UserRepository, MessageRepository, LocationRepository, each of which accepts an EF DbContext object as a constructor parameter. This lets me control the Unit of Work at the context level, by calling context.Save() or rollback etc to control transactioning across repositories.
The confusion I'm in is that I'm not sure how to represent this in dependency injection. I want to have two scenarios
a) When the WCF service is instantiated via the WCF methods, I want it to use the DbContext class I have created and to create repository objects, passing in the created DbContext that will connect to the Entity Framework database.
b) When the WCF service methods are tested from a separate test project, I want to mock the repository objects to return mocked data.
If I was just using repository classes, this would be relatively simple as in each WCF service method I could call Container.Resolve() and then I could use the Unity WCF factory to set the concrete types for WCF instantiation, and manually configure the Unity container in my test project for the mocked types.
But the difficulty is the fact that my repositories need a DbContext class to be passed in as a constructor parameter that will survive beyond the lifetime of the repository and I also need to be able to have a reference to it in my service methods, for example
public bool CreateUser(DbUser user)
{
try
{
using (var context = new MyDbContext())
{
var repository = new UserDataRepository(context);
user.GenerateUserLight();
user.GenerateUserProfileLight();
var result = repository.InsertItem(user);
repository.Save();
return result;
}
}
catch (Exception ex)
{
return false;
}
}
How can I adapt the above method to use Unity Dependency injection so I can mock it for the test project?
As far as I can see the issue here is that you should be creating your context within your repository, the fact that you are actually newing up the context in the service and then passing it into your repository is a bit of a code smell.
Why not have the repositories handle the DbContext? That way you are not coupling your repositories to Entity Framework in the first place.
The service should only have a dependency on an IUserRepository interface.. not the concrete implementation.
private readonly IUserRepository _userRepository;
public MyService(IUserRepository userRepository)
{
this._userRepository = userRepository;
}
public bool CreateUser(DbUser user)
{
try
{
user.GenerateUserLight();
user.GenerateUserProfileLight();
var result = this._userRepository.InsertItem(user);
this._userRepository.Save();
return result;
}
catch (Exception ex)
{
return false;
}
}
The user repository would accept a DbContext in its constructor, you would need to register the context with the DI container also so that the DI can construct the UserRepository when it's injected into the service.
public class UserRepository : IUserRepository
{
private readonly MyDbContext context;
public UserRepository(MyDbContext context)
{
this.context = context;
}
}
Then you could simply inject the "UserRepository" into the service via the constructor.
This would also enable you to create Mock repository types that don't need a context at all, simply create an interface for your repository.

Use of context and repository in EF WCF services

I am using Entity Framework code first in my data layer using the repository pattern. I'm currently designing my WCF web services to connect to the data layer and I'm just a little confused about how to link up with the data layer.
In my test project for the data layer I create a new DbContext class for each test, wrap that in a using block, within that I create the repository class, passing in the context as the constructor parameter. I can then call my methods on the repository to get the data back.
Is this correct for a start and then do I do the same in the WCF service methods?
Eg would I have
public class UserService : IUserService
{
public bool CheckEmailAvailability(string email)
{
try
{
using (var context = new MyDbContext())
{
var repository = new UserDataRepository(context);
var emailAvailable =
repository.GetItems().Count(
u => u.EmailAddress.Equals(email, StringComparison.InvariantCultureIgnoreCase)) == 0;
return emailAvailable;
}
}
}
}
Or am I using the context/repository concept wrong?
It also strikes me that it would be handy to use DI here so I could mock the data context/repository objects in a WCF service test project. Is this something usually done and if so, does anyone have any links to an example or tutorial on this?
First of all, yes it would be better to inject the repository, or (if your chosen DI framework is unable to resolve them) a factory for the repository.
Additionally it might be a good idea to remove the idea of the context from your service. To my mind the repository and it's helpers should deal with the context, and if necessary with sharing the context between various DB calls required to assemble your entities. Then the services can request entities from the repositories without worrying about whether they're being source from a DB or some other data-store.
public class UserService: IUserService
{
IUserRepository userRepository;
... // ctor to inject repository
public bool CheckEmailAvailability(string email)
{
var emailAvailable = !userRepository.GetUserEmails().Any(u => u.EmailAddress.Equals(email, StringComparison.InvariantCultureIgnoreCase));
return emailAvailable;
}
}
public class UserRepository: IUserRepository
{
...
public IEnumerable GetUserEmails()
{
// actually this context should be handled more centrally, included here for sake of illustration
using (var context = new MyDbContext())
{
return repository.GetItems();
}
}
}
Finally, with regard to WCF services, I'm not certain what the best advice is. I've seen code where WCF services were created in the middle of business logic, which was awful, but a limitation of the oldish WPF code-base and limited DI. The better situations are where a ChannelFactory or service factory can be injected into your service layer. You may find this answer on Dependency Injection wcf helpful.
And as always, if you're planning to TDD your code, I'd definitely recommend wrapping the intersection points between layers of your application in interfaces so that they're easier to mock out. It sounds like you've got the right idea there.

Categories

Resources