I would like to implement IdbSet to provide my DbContext a custom implementation that will essentially serve to filter my data for the currently logged in user (I am working on a multi-tenant application). The general idea I am going with is very similar to this post: Can a DbContext enforce a filter policy?
However, it is not clear to me how to make DbContext "know" about how to use my own class that implements IDbSet. I am having a tough time finding documentation on this. Any pointers would be helpful!
TIA,
-jle
I'm almost sure that you cannot create your own implementation of IDbSet and pass it to entity framework. Such implementation will lose all stuff related to EF which is internally implemented in DbSet itself - by internally I really mean that there is no public API to replace it. IDbSet interface is provided not because it is supposed to create your own sets but because it allows mocking sets when unit testing application. The only way you can extend functionality is either:
Inheriting DbSet but I'm afraid that it will not help you as well because methods / properties will not be marked as virtual.
Creating custom IDbSet implementation which will wrap DbSet. This looks like the best chance but you can still find that DbContext doesn't like your new implementation. I gave this very quick try but I was not successful. My implementation worked for persisting but not for querying.
Related
I'm currently trying out a few different ways of implementing repositories in the project I'm working on, and currently have a single repository with generic methods on it something like this:
public interface IRepository
{
T GetSingle<T>(IQueryBase<T> query) where T : BaseEntity;
IQueryable<T> GetList<T>(IQueryBase<T> query) where T : BaseEntity;
T Get<T>(int id) where T : BaseEntity;
int Save<T>(T entity) where T : BaseEntity;
void DeleteSingle<T>(IQueryBase<T> query) where T : BaseEntity;
void DeleteList<T>(IQueryBase<T> query) where T : BaseEntity;
}
That way I can just inject a single repository into a class and use it to get whatever I need.
(by the way, I'm using Fluent NHibernate as my ORM, with a session-per-web-request pattern, and injecting my repository using Structuremap)
This seems to work for me - the methods I've defined on this repository do everything I need. But in all my web searching, I haven't found other people using this approach, which makes me think I'm missing something ... Is this going to cause me problems as I grow my application?
I read a lot of people talking about having a repository per root entity - but if I identify root entities with some interface and restrict the generic methods to only allow classes implementing that interface, then aren't I achieving the same thing?
thanks in advance for any offerings.
I'm currently using a mix of both generic repositories (IRepository<T>) and custom (ICustomRepository). I do not expose IQueryable or IQueryOver from my repositories though.
Also I am only using my repositories as a query interface. I do all of my saving, updating, deleting through the Session (unit of work) object that I'm injecting into my repository. This allows me to do transactions across different repositories.
I've found that I definitely cannot do everything from a generic repository but they are definitely useful in a number of cases.
To answer your question though I do not think it's a bad idea to have a single generic repository if you can get by with it. In my implementation this would not work but if it works for you then that's great. I think it comes down to what works best for you. I don't think you will ever find a solution out there that works perfectly for your situation. I've found hybrid solutions work best for me.
I've done something similar in my projects. One drawback is that you'll have to be careful you don't create a select n+1 bug. I got around it by passing a separate list of properties to eagerly fetch.
The main argument you'll hear against wrapping your ORM like this is that it's a leaky abstraction. You'll still have to code around some the "gotchas" like select n+1 and you don't get to take full advantage of things like NH's caching support (at least not without extra code).
Here's a good thread on the pros and cons of this approach on Ayende's blog. He's more or less opposed to the pattern, but there are a few counter arguments too.
I've implemented such kind of repository for NHibernate. You can see example here.
In that implementation you are able to do eager loading and fetching. The pitfall is that with NH you will often need to be able to use QueryOver or Criteria API to access data (unfortunately LINQ provider is still far from being perfect). And with such an abstraction it could be a problem leading to leaky abstraction.
I have actually moved away from repository pattern and creating a unit of work interfaces - I find it limiting.
Unless you anticipate a change in the datastore i.e. going from DB to textfile or XML - which has never been the case for me, you are best off using ISession. You are trying to abstract your data access and this is exactly what NHibernate does. Using repository limits really cool features like Fetch(), FetchMany() futures etc. ISession is your unit of work.
Embrace NHibernate and use the ISession directly!
I've used this approach successfully on a few projects. It gets burdensome passing in many IRepository<T> to my Service layers for each BaseEntity, but it works. One thing I would change is put the where T : on the interface rather than the methods
public interface IRepository<T> where T : BaseEntity
i'm using DDD architecture in my project and I need to create a class to generate a GUID to use in another class.
This class that generate my GUID is a Infrastructure Service or a Infrastructure Helper?
How I know when a class is a Helper or a Service?
Service able to serve some clients, and often this is a SOA specific entity.
Helper provides a set of methods which commonly are pure functions.
From my point of view if a class which provides the GUID generation functionality stores or uses this GUID for further needs - it is a Service class, otherwise I would say it is a Helper because simply work by principle do and forget / generate and forget.
Often if you can make method a static method - this is a helper method, it does not depends on any class state and does not affect it as well.
Glad you found an answer but you might want to rethink the question itself. What is 'Helper'? There is no such pattern or stereotype in DDD or anywhere else. Take a look at this answer. [Something]Helper is usually a sign of SRP violation or just a bad naming. For example if your language/framework does not provide Guid generation (which is highly unlikely) you can create your own GuidGenerator class. The name should reflect responsibility.
I've seen it mentioned sometimes that Repository Pattern is built into Entity Framework Code First via the DbSet and DbContext objects.
However that leaves a few problems:
1) Injection - Hard to inject as there isn't a clear cut Interface
2) Mocking - Same as above
3) Multiple references to EnitityFramework.dll - Let's say I create my Code First in it's own assembly/project and then want to reference that in another place I also have to reference entityFramework.dll without some wrapper present
Do you aggree with this and what do you think is the best solution if you do?
DbSet has interface and you usually implement your own context class derived from DbContext so it can also implement your own interface allowing you to deal with injection without any problem.
This is more complex issue. Mocking context doesn't make sense, mocking IDbSet doesn't make sense as well but in the same time mocking any repository or wrapper exposing IQueryable or accepting Expression<Func<>> passed to Linq-to-entities doesn't make sense either (here is simple example why). So yes repository can handle this but you will have to put more effort into this and you will not use Linq to query database from code calling your repository. If you want your upper layer to use declarative queries (as expected when using repository) you must implement your own specifications.
Imho if you don't have EntityFramework.dll in GAC and you will reference your first assembly from new solution you will still add reference to EntityFramework.dll to make sure that it is deployed with your code. Otherwise you are right. Without wrapper you need a reference.
If I implement some simple OR/M tool, where do I put identity map? Obviously, each Repository should have access to its own identity map, so it can register loaded objects (or maybe DataMapper is the one who registers objects in IdentityMap?).
And when I commit unit of work, I also need to access the identity map to see which entity is dirty and which is clean (or I am wrong again and there is some outer object which calls RegisterClean/RegisterDirty methods of my UnitOfWork class? Then what object does this?).
Does this mean that I should implement IdentityMap as a completely independent object which contains inner IdentityMaps for each entity type?
Really confused about how IdentityMap, Repository and UnitOfWork work all together.
With our .NET O/R Mapper, LightSpeed we placed the identity map inside the unit of work class. This has worked very well for us and feels quite natural as it effectively acts as a level 1 cache for querying purposes during the unit of work's life.
Generally, inject or somehow provide a UoW for your Repository class so that you have an effective scope and gateway to querying.
I hope that helps.
I'm trying to get to grips with NHibernate, Fluent NHibernate and Spring.
Following domain-driven design principals, I'm writing a standard tiered web application composed of:
a presentation tier (ASP.Net)
a business tier, comprising:
an application tier (basically a set of methods made visible to UI tier)
repository interfaces and domain components (used by the application tier)
A persistence tier (basically the implementation of the repository interfaces defined in the business tier)
I would like help determining a way of instantiating an NHibernate ISession in such a way that it can be shared by multiple repositories over the lifetime of a single request to the business tier. Specifically, I would like to:
allow the ISession instance and any transaction to be controlled outwith the repository implementation (perhaps by some aspect of the IOC framework, an interceptor?)
allow the ISession instance to be available to the repositories in a test-friendly manner (perhaps via injection or trough some shared 'context' abstraction)
avoid any unnecessary transactions being created (i.e. when only read-only operations have been executed)
allow me to write tests that use SQLLite
allow me to use Fluent NHibernate
allow the repository implementation to remain ignorant of the host environment. I don't yet know if the businese tier will run in-process with the presentation tier or will be hosted separately under WCF (in IIS), so I don't want to bind my code too closely to a HTTP context (for example).
My first attempt to solve this problem had been using the Registry pattern; storing the ISession instance in a ThreadStatic property. However, subsequent reading has suggested that isn't the best solution (as ASP.Net can switch the thread within the page lifecycle, I believe).
Any thoughts, part solutions, pattern names, pointers to up-to-date samples (NHibernate 2) will be most gratefully received.
I have not used Spring.NET so I can't comment on that. However, the rest sounds remarkably (or perhaps not so remarkably; we're hardly the first to implement these things ;) similar to my own experience. I too had trouble finding a One True Best Practice so I just read as much as I could and came up with my own interpretation.
In my situation I wanted transaction/session management to be external to the repository as well as keep repository concerns from bubbling up out of them (i.e. the code using the repository should not need to know that it's using NHibernate internally and shouldn't need to know anything about NHibernate session management). In my case it was decided that transactions would be created by default lest developers forget them, so I had to have a read-only escape mechanism. I went with the Unit of Work pattern with the NHibernate ISession instance store inside. Calling code (I also created a DSL interface for the UoW) might look something like:
using (var uow = UoW.Start().ReadOnly().WithHttpContext()
.InNewScope().WithScopeContext(ScopeContextProvider.For<CRMModel>())
{
// Repository access
}
In practice, that could be as short as UoW.Start() depending on how much context is already available. The HttpContext part refers to the storage location for the UoW which is, unsurprisingly, the HttpContext in this case. As you mentioned, for a ASP .NET application, HttpContext is the safest place to store things. ScopeContextProvider basically makes sure the right data context is provided for the UoW (ISession instance to the appropriate database/server, other settings). The "ScopeContext" concept also makes it easy to insert a "test" scope context.
Going this route makes the repositories explicitly dependent on the UoW interface. Actually, you might be able to abstract it some but I'm not sure I see the benefit. What I mean is, each repository method retrieves the current UoW instance and then pulls out the ISession object (or simply a SqlConnection for those methods that don't use NHibernate) to run the NHibernate query/operation. This works for me though because it also seems like the ideal time to make sure that the current UoW is not read-only for methods that might need to run CRUD.
Overall, I think this is one approach that solves all your points:
Allows session management to be external to the repository
ISession context can be mocked or pointed at a context provider for a test environment
Avoids unnecessary transactions (well, you'd have to invert what I did and have a .Transactional() call or something)
I can't see why you couldn't test with SQLite since that's more of an NHibernate concern
I use Fluent NHibernate myself
Allows the repository to be ignorant of the host environment (that is, the repository caller controls the UoW storage context)
As for the UoW implementation, I'm partially kicking myself for not looking around more before I started. There's a project called machine.uow which I understand is fairly popular and works well with NHibernate. I haven't played with it much so I can't say if it solves all my requirements as neatly as the one I wrote myself, but it might have saved development time as well.
Perhaps we'll get some comments as to where I went wrong or how to improve things, but I hope this is at least helpful in some way.
For reference, the software stack I'm using is:
ASP.NET MVC
Fluent NHibernate on top of NHibernate
Ninject for dependency injection
What you are describing is supported by the Spring.NET framework almost out of the box. Only for FluentNHibernate you need to add a custom SessionFactory (not a lot of code, look here:Using Fluent NHibernate in Spring.NET) to Spring.NET.
Every repository can use the same ISession, just inject the SessionFactory in your repositories and use Spring.NET's transaction services.
Just try it out, they have pretty thorough documentation imho.