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.
Related
I am developing a web API in .NET Core with multiple DataContexts(DbContext). I have used repository pattern to handle DB calls. The Repository class accepts a DbContext as a generic type.
public class Repository<T> : IRepository where T : DbContext
{
public Repository(T context) : base(context)
{
}
}
This Repository class injects to service classes as IRepository from the Startup. I want to connect with 2 databases. So I`m using 2 DataContext classes and passed them in to repository class in the startup.
Here is my Startup class,
services.AddTransient<DataContext1>(x => new DataContext1(Configuration.GetConnectionString("Database1")));
services.AddTransient<IRepository, Repository<DataContext1>>();
services.AddTransient<DataContext2>(x => new DataContext2(Configuration.GetConnectionString("Database2")));
services.AddTransient<IRepository, Repository<DataContext2>>();
When I request IRepository it always injects the Repository class with the last DataContext(DataContext2). What is the best way to solve this problem without affecting to the API performance(Memory / CPU).
Here is my Service class,
private readonly IRepository _repository;
public BookService(IRepository repository)
{
_repository = repository;
}
I think you should at least create one repository interface for each type of database in order of the dependency injection system can handle it.
Inject a factory class for the repositories instead of an instance of the repositories themselves. Implement the factory methods to suit your needs.
I'm trying to set the variable DB as global and use anywhere.
My problem is that I'm initialising twice the db. In the base controller and in atributes.
ie:
public class SettingsAttribute : ActionFilterAttribute {
public ApplicationDbContext db = new ApplicationDbContext();
public override void OnActionExecuting(ActionExecutingContext filterContext) {
...
}
and
[Settings]
public class BaseController : Controller {
public ApplicationDbContext db = new ApplicationDbContext();
protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state) {
...
}
I would like to create the var db just once, and access anywhere in the project.
How ca I do this?
Consider using of Dependency Injection pattern. For .NET there is for example Unity container, which implements a lightweight, extensible dependency injection container. Check the List of dependency injection containers for .NET, but it's quite old.
In general, Dependency injection is called Inversion of Control (IoC). That means, your classes, which are using for example your DB class, don't need to be dependent on a specific DB class. Instead, they just require a specific interface. DB class implementing this interface is injected from the outside and your class is decoupled from a specific implementation of DB class.
Some places to start with:
Dependency Injection on Wikipedia.org
Why does one use dependency injection?
An Absolute Beginner's Tutorial on Dependency Inversion Principle, Inversion of Control and Dependency Injection
Dependency Injection in Windows Communication Foundation
What about putting it in another class (an Helper, for instance), and access it like this:
private ApplicationDbContext db = null;
public ApplicationDbContext Db {
get {
if (db == null)
db = new ApplicationDbContext();
return db;
}
}
Best practice in this situation and (similar situations) is to implement a DI/IoC pattern , as #Dawid-Ferenczy mentioned in his answer. if you never worked with it before , it's a little abstract at the beginning but it's very useful in the long run , especially if your objects got complicated. You can search online for articles to learn more about the pattern itself.
#Dawid-Ferenczy mentioned the Unity container, but it's not limited to that , you can use any container you would like (Or even create your own if you need to ).
I personally use Ninject as it has a has a lot of support documentation and i found it easy to implement.
In your case (DB context) i would use Ninject and DI/IoC as follow:
1- Declare an interface for your DB Context DAL:
public interface IModelDBContext
{
//Your methods should go here
}
Your concrete class:
public class ModelDBContext : DbContext,IModelDBContext
{
//Your methods and other stuff here
}
Container part
(Ninject in my case , but you can use any other container)
public class NinjectDependencyResolver : IDependencyResolver
{
//Bunch of initialization and methods
Check out this : [Using ninject in MVC][2].
//Binding piece (Very important)
private void AddBindings()
{
//Context DB Binding
kernel.Bind<IModelDBContext>().To<ModelDBContext>();
//Other binding
}
}
Implementation part:
This is the fun and exciting part. anywhere in your application , if you need to implement your specific DB context you inject it with the constructor and it will be available for you to use:
In your case it will be something like this:
Public YourConcreteClass
{
Private IModelDBContext ModelDB; //Initiate an instance that you will use .
//DI by constructor
public YourConcreteClass(IModelDBContext mDB)
{
ModelDB=mDB;
}
//in the rest of your code you call ModelDB that has access to all of the methods and attributes you might need
}
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.
I have a layered application with the following projects:
DAL (using EntityFramework with repositories)
DAL.Model (contains the entities, and is referenced by all the others)
Services
UI (in wpf)
The base repository looks like this:
public abstract class RepositoryBase<T> where T : class
{
private readonly MyContext context;
private readonly IDbSet<T> dbSet;
protected RepositoryBase(MyContext dataContext)
{
context = dataContext;
dbSet = context.Set<T>();
}
protected MyContext Context
{
get { return context; }
}
**And a series of virtual methods for Add, Delete, etc.
}
All repositories extend this one, such as:
public class MarketRepository : RepositoryBase<Market>
{
public MarketRepository(MyContext dataContext) : base(dataContext)
{
}
public IEnumerable<Market> GetAllMarkets()
{
return this.Context.Markets.ToList<Market>();
}
}
The services look like this:
public class MarketService
{
IMarketRepository _marketRepository;
public MarketService(IMarketRepository marketRepository)
{
_marketRepository = marketRepository;
}
public IEnumerable<Market> GetAllMarkets()
{
return _marketRepository.GetAllMarkets();
}
}
What I would like to achieve is that the UI layer would only have a reference to the Services layer, the Services layer only with the DAL layer (and all of them to Model, where the entities live) using DI (right now I'm using Unity).
The problem is, in my container in the UI I only want to do this
unity.RegisterType<IMarketService, MarketService>();
and not have to do it as well for the repositories, because then the UI layer would have a dependency on the DAL layer.
I thought about adding a parameterless constructor to the Service classes, like:
public MarketService() : this(new MarketRepository(*What would I put here?)) { }
but then I'm loosing the abstraction that the interface gives, and also I don't know what to do with the MyContext that the repository needs as a parameter; if I pass a new one, then I need to reference the DAL.
Should I change my repositories to create a new MyContext in the constructor, rather than getting it as a parameter?
How can I refactor my architecture to make it work properly and with minimal dependencies?
Well, I belive it is up to the bootstrapper to configure dependencies, in the higher level of the application. As it is usually the UI project, if it needs to reference other assemblies, so be it. If you do not like your UI project managing that, than create a bootstrapper project responsable for getting your app running and separete your UI classes in another one.
Your IoC container should support Dependency Injection using a string from an external configuration file. This way you are not hardcoding the mapping. Structuremap does this quite well, so I am sure other IoCs will.
Adding external dependenices as a parameter when creating an instance is the way to go.
I think you should make yourself more familiar with the different ways to configure Unity, so that the dependencies are resolved.
Could you elaborate why you are creating a repository when using a dependency injection framework?
When configuring DI, you should follow the same pattern - UI bootstrapper initializes Services, Services initialize DAL. (With autofac or ninject you could achiece this using modules. With unity you should emulate modules).
In pseudocode something like
//ui
void UILayer.ConfigureUnity(unity)
{
ServiceLayer.ConfigureUnity(unity)
}
//services
void ServiceLayer.ConfigureUnity(unity)
{
DAL.ConfigureUnity(unity)
unity.RegisterType<IMarketService, MarketService>();
}
//dal
void DAL.ConfigureUnity(unity)
{
unity.RegisterType<IMarketRepository, MarketRespository>();
unity.RegisterType<MyContext, MyContext>(); //not sure exact syntax - just register type for 'new Type()' activator.
}
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;
}
}