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.
Related
I'm currently building a large solution for a client where code reuseability is the keyword since different types of projects (i.e. Websites, WCF services, WPF etc) should use the exact same businesslogic.
Right now, my solution looks like this:
Businesslogic layer (all of the logic that defines business rules is added here)
Interfaces
Model (ViewModels, DTOs etc)
Repository (currently using Entity Framework 6. This is where all database transactions go)
Webservices (WCF services)
MVC website
The point is that any presentation layer (i.e. the MVC website) will use the businesslogic layer which then uses the repository to make any database transaction needed.
While this works the way I want to, I find myself constantly battleing the ObjectContext from the Entity Framework, simply because, when querying for data in the repository, the entities doesn't get transferred to the businesslogic (which is logical because of EFs lazy-loading) I'm aware that I can make use of the .Include(x => x.MyOtherTable), but since the database is fairly large, this approach gets bloated quickly and queries can be rather large if the included table has a lot of records.
I've then made a DbContextManager class which looks like this:
public static class DbContextManager
{
//Unique context key per request and thread
private static string Key
{
get
{
return string.Format("MyDb_{0}{1}", HttpContext.Current.GetHashCode().ToString("x"), Thread.CurrentContext.ContextID);
}
}
//Get and set request context
private static MyEntities Context
{
get { return HttpContext.Current.Items[Key] as MyEntities ; }
set { HttpContext.Current.Items[Key] = value; }
}
//Context per request
public static MyEntities Current
{
get
{
//if null, create new context
if (Context == null)
{
Context = new MyEntities ();
HttpContext.Current.Items[Key] = Context;
}
return Context;
}
}
//Dispose any created context at the end of a request - called from Global.asax
public static void Dispose()
{
if (Context != null)
{
Context.Dispose();
}
}
}
And in my global.asax, I'm disposing the context when a request is ended:
private void Application_EndRequest(object sender, EventArgs e)
{
DbContextManager.Dispose();
}
This works perfect, I can now make my initial database call in the repository and then make the businesslogic rules in my businesslogic layer, simply because the ObjectContext lives for the http request.
However, when I need to call the same businesslogic methods from the WCF services project (or i.e. a WPF project), I won't be able to make use of my DbContextManager class since it relies on the HttpContext.
I feel I'm doing this completely wrong at the moment and I'm fighting an unnessecary battle with the Entity Framework. What have I missed? Is Entity Framework the right ORM for these types of solutions? It certainly doesn't feel like that right now :-)
Any help or hints are greatly appreciated!
Thanks in advance.
I'm confused here. It looks like you are using your entity layer objects directly in your view layer.
This is generally a bad idea. Your model should encapsulate these. Your business logic layer should use your model layer to build ViewModel and DTO objects, which the UI layer can produce/consume. This will allow you to fully separate your UI layer from your database/entity layer.
That will make re-using your business logic in a web service layer trivial. It should know nothing of your database layer. Otherwise adding or changing a field in your entity layer will have a direct impact on all the UI layers.
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.
My implementation of unit of work and repository might be the root of the issue here.. but given that everywhere I look for a unit of work implementation I see a different one, I'm sure Ninject has a way of working around it.
So I'm injecting implementations of IRepository<T> into the constructor of my "unit of work".
_kernel.Bind<IRepository<SomeType1>>().To<RepoOfSomeType1>().WhenInjectedInto<IMyUoWFactory>();
_kernel.Bind<IRepository<SomeType2>>().To<RepoOfSomeType2>().WhenInjectedInto<IMyUoWFactory>();
...
I've set up the kernel to instantiate a DataContext in singleton scope which I thought would mean I'm injecting the same instance of this DataContext whenever I need it:
_kernel.Bind<DataContext>().ToConstructor(arg => new MyDataContext(arg.Inject<string>()))
.InSingletonScope() // pass same instance to all repositories?
("connection", _someConnectionString);
The problem I'm finding, is that each repository seems to have its own instance, plus the unit of work has its own as well - hence the exception I'm getting when I try to commit a transaction (something about cross-context transaction).
To top it all off, in certain specific situations I need the connection string to be dynamic, so that the unit of work can work off a database that's selected by the user - hence the "need" for a factory.
The result is that I have 1 connection per repository plus 1 connection per unit of work, which defeats the purpose of UoW (i.e. transactional data operations), and all this overhead, I think, is causing serious performance issues (running +/- 200,000 small data operations in... 3-4 hours!!).
This is how I'm creating the unit of work instance; I want to be able to inject repository implementations in there, yet still be able to use the connection string that the user asked for:
public MyUoWFactory(IRepository<Type1> type1repo, IRepository<Type2> type2repo,
IRepository<Type3> type3repo, IRepository<Type4> type4repo,
IRepository<Type5> type5repo, IRepository<Type6> type6repo)
{
_type1Repository = type1repo;
_type2Repository = type2repo;
_type3Repository = type3repo;
_type4Repository = type4repo;
_type5Repository = type5repo;
_type6Repository = type6repo;
}
public IUnitOfWork Create(string userSelectedConnectionString)
{
return new MyUoW(new MyDataContext(userSelectedConnectionString),
_type1Repository, _type2Repository, _type3Repository,
_type4Repository, _type5Repository, _type6Repository);
}
With the kernel bindings I've defined, this causes the DataContext of the repositories to point where the kernel dictates, and the DataContext of the created UoW to point where the user asked for.
How can I pull this off without resorting to service locator? I need the repositories to have their DataContext injected not at app start-up, but after the user has selected a database. Is this where Ninject.Factory comes into play?
Argh.. did it again (finding answer shortly after posting in premature despair). What I wanted was the unit of work factory to actually create the repositories. So the answer is pretty simple: instead of injecting IRepository<T>, I created an interface IRepositoryFactory<T> and injected that instead:
public interface IRepositoryFactory<T> where T : class
{
IRepository<T> Create(DataContext context);
}
This way the Create method of MyUoWFactory taking the user-selected connection string could create only one context and pass it to all repository factories:
public MyUoWFactory(IRepositoryFactory<Type1> type1repoFactory, IRepositoryFactory<Type2> type2repoFactory,
IRepositoryFactory<Type3> type3repoFactory, IRepositoryFactory<Type4> type4repoFactory,
IRepositoryFactory<Type5> type5repoFactory, IRepositoryFactory<Type6> type6repoFactory)
{
_type1RepositoryFactory = type1repoFactory;
_type2RepositoryFactory = type2repoFactory;
_type3RepositoryFactory = type3repoFactory;
_type4RepositoryFactory = type4repoFactory;
_type5RepositoryFactory = type5repoFactory;
_type6RepositoryFactory = type6repoFactory;
}
public IUnitOfWork Create(string userSelectedConnectionString)
{
var context = new MyDataContext(userSelectedConnectionString)
return new MyUoW(context,
_type1RepositoryFactory.Create(context),
_type2RepositoryFactory.Create(context),
_type3RepositoryFactory.Create(context),
_type4RepositoryFactory.Create(context),
_type5RepositoryFactory.Create(context),
_type6RepositoryFactory.Create(context));
}
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 need presentation layer in silverlight, asp.net etc , so everything is through wcf services.
I have number of doubts in my implementation of repository layer, service layer, wcf services
things i currently do
I have repository , its not per table its created per aggregate root
I have service layer its for doing a group of actions involving multiple repository
WCF service wraps the methods in service layer and repository layer
The entities are auto generated by EF
The entities are passed and returned to service layer as complete graph
6.I have two concrete class with all repository , and service called repositorycontainer and service container , Repository container is passed to the service
My repository base
public class RepositoryBase
{
public DataBaseContext _Context;
public RepositoryContainer _RepositoryContainer;
public RepositoryBase(RepositoryContainer repositoryContainer)
{
_RepositoryContainer = repositoryContainer;
_Context = repositoryContainer.Context;
}
public RepositoryBase()
{
_RepositoryContainer = new RepositoryContainer();
_Context = _RepositoryContainer.Context;
}
}
My repository container
public class RepositoryContainer
{
public RepositoryContainer()
{
Context = new DataBaseContext();
}
public RepositoryContainer(DataBaseContext context)
{
Context = context;
}
public DataBaseContext Context
{
get;
set;
}
public SurveyRepository _SurveyRepository;
public SurveyRepository SurveyRepository
{
get
{
return _SurveyRepository ?? (_SurveyRepository = new SurveyRepository(this));
}
}
}
My service container
public class ServiceContainer
{
public ServiceContainer()
{
RepositoryContainer = new RepositoryContainer();
}
public ServiceContainer(RepositoryContainer container)
{
RepositoryContainer = container;
}
public RepositoryContainer RepositoryContainer
{
get;
set;
}
public SurveyService _SurveyService;
public SurveyService SurveyService
{
get
{
return _SurveyService?? (_SurveyService= new SurveyService(this));
}
}
}
To do an operation
I just create RepositoryContainer or ServiceContainer
then calls
RepositoryContainer.Repository.Method()
ServiceContainer.Service.Method()
My doubts are
Is that service / respository container fine ?
I already have the service layer, so as i have wcf service what i call the current service layer servicewrapper or something ?
I need to call repository methods itself eg: GetCategory() etc , also all methods in service layer, So i need to wrap both methods and service in wcf service, is it fine ?
Where to do the caching ? as i am using EF i think there is something way to use a cache provider with EF ,
Is that service / respository
container fine ?
The RepositoryContainer class contains a "SurveyRepository" - but shouldn't the SurveyRepository be an instance of a RepositoryContainer? Same for ServiceContainer and "SurveyService". It would make more sense to me if they were (although it's hard to comment accurately without being more familiar with the project).
You'd then have: ServiceContainer SurveyService = new ServiceContainer(..);
As you have it, I get the impression that "SurveyService" is a specific business concept but it's wrapped up in a more generic type (ServiceContainer); same for SurveyRepository / RepositoryContainer.
This will break SRP, Common Closure Principle and probably Common Reuse Principle.
I'm not sure what other think, but I'm also not a fan of naming instances after their types (except in the most basic of senarios - which this isn't): public SurveyRepository SurveyRepository The name of the type should reflect what the type is (or does) which will be quiote different from a specific instance of it (like ServerContainer and ServeyService).
I already have the service layer, so
as i have wcf service what i call the
current service layer servicewrapper
or something ?
and
So i need to change name of my service
(BL) layer to something service
wrapper or something , then in wcf
service layer i define methods in
repository and service then just calls
curresponding methods in service,
repository
Generally any reusable BL should be in a standalone package and not enclosed (think "hard-coded") in a service layer or WCF service, etc. You'd then create service end-points that sat on top of the BL. If you have business transactions that span different business objects within different packages then you'll need to put that higher level orchestration somewhere higher - I guess this could go in the service layer, but this isn't a trival thing to do, you'll need to carefully consider where certain responsibilities lie.
If the transaction scover different business objects within the same package then the orchestration is much simpler and can be done with another BL type designed to handle that job, which will be part of that package - and not in the service layer.
Regarding the naming - go to a whiteboard and map everything out, and then rename everything as required. At least with a single cohesive overview you'll be able to make clear sense of everything.
BL packages should be named as appropriate to what they do - in business terms. WCF services that wrap these should have a name that fits and this could include reference to the type of channel being used (JSON, WebService, etc). Because you can change the channel a WCF service uses by config (if the service is design correctly) this might not be a good idea - but assuming it doesn't then the extra clarity might be helpful.
These articles might be of help:
http://blogs.oracle.com/christomkins/2009/07/my_thoughts_on_service_naming.html
http://ea.typepad.com/enterprise_abstraction/2006/08/service_naming_.html
What naming convention do you use for the service layer in a Spring MVC application?
I need to call repository methods
itself eg: GetCategory() etc , also
all methods in service layer, So i
need to wrap both methods and service
in wcf service, is it fine ?
Wrapping a service in a service sounds a bit suspect. Only external callers should go through the services - assuming the services are designed to expose the BL to external parties. Internal callers should know which is the appropriate method to call (by virtue of being internal), presumably it's the same method that is exposed by the service.
Where to do the caching ? as i am
using EF i think there is something
way to use a cache provider with EF
I don't know if you can cache in EF4 but it wouldn't surprise me if you can. Where to do caching? - it depends on where the bottle kneck is that you're trying to eliminate.
In your RepositoryContainer, the _SurveyRepository field is public - shouldn't it be private? Otherwise why have a read-only (get) SurveyService property?
public SurveyRepository _SurveyRepository;