I am currently playing around with the HybridSessionBuilder class found on Jeffrey Palermo's blog post:
http://jeffreypalermo.com/blog/use-this-nhibernate-wrapper-to-keep-your-repository-classes-simple/
Using this class, my repository looks like this:
public class UserRepository : IUserRepository
{
private readonly ISessionBuilder _sessionBuilder;
public UserRepository(ISessionBuilder sessionBuilder)
{
_sessionBuilder = sessionBuilder;
}
public User GetByID(string userID)
{
using (ISession session = _sessionBuilder.GetSession())
{
return session.Get<User>(userID);
}
}
}
Is this the best way to go about managing the NHibernate session / factory? I've heard things about Unit of Work and creating a session per web request and flushing it at the end. From what I can tell, my current implementation isn't doing any of this. It is basically relying on the Repository to grab the session from the session factory and use it to run the queries.
Are there any pitfalls to doing database access this way?
You should not wrap your ISession in a using statement -- the point of passing the ISessionBuilder into the repository constructor (dependency injection) is that the calling code is responsible for controlling the life cycle of the ISession. By wrapping it in a using, Dispose() is called on the ISession and you won't be able to lazy load object members or persist it.
We do something similar by just passing in an ISession to the repository constructor. Mr. Palermo's code, as I understand it, simply adds lazy initialization of the ISession. I don't think that's needed because why would you new up a repository if you're not going to use it?
With ASP.Net MVC you want to make sure the life of the session is maintained during the Action method on your controller, as once your controller has exited all your data should be collected. I am not sure if this mechanism will help with that.
You might want to look into S#arp Architechure which is a set of libraries and guidance for building ASP.Net MVC application using nHibernate. http://code.google.com/p/sharp-architecture/
This is the setup I used after researching this more. Seems to work great and doesn't have that annoying habit of creating an ISession on static file requests like most guides out there:
http://www.kevinwilliampang.com/2010/04/06/setting-up-asp-net-mvc-with-fluent-nhibernate-and-structuremap/
I wouldn't open and close sessions on each data request to NHibernate. I would use the Unit of Work libraries that many others suggest or do some more reading. NHForge.org is getting started and I believe that there are some practices on setting up NHibernate for a general web application.
One of the "oh wow that's cool moments" that I've gotten from NHibernate was taking advantage of lazily loading collections during development. It was a neat experience being able to not have to do all those joins in order to display data on some associated object.
By closing the session like this, the above scenario would not be possible.
There might be something that is going on with transactions as well.
Just found a clean solution using Unity to inject a session per request:
http://letsfollowtheyellowbrickroad.blogspot.com/2010/05/nhibernate-sessions-in-aspnet-mvc.html
Related
I have an MVC3 application that is using Ninject and MvcSiteMapProvider.
I have created this class which MvcSiteMapProvider uses to dynamically add nodes to my sitemap:
public class PageNodeProvider : DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection()
{
// need to get repository instance
var repository = // how do I get this???
foreach (var item in repository.GetItems())
{
yield return MakeDynamicNode(item);
}
}
}
The MvcSiteMapProvider instantiates this type itself, so I'm not sure how to inject my repository into it.
I thought about using service location by getting a handle on my kernel and calling Get<Repository>() in the method. But, I saw this property when looking at the definition of NinjectHttpApplication:
// Summary:
// Gets the kernel.
[Obsolete("Do not use Ninject as Service Locator")]
public IKernel Kernel { get; }
Do not use Ninject as Service Locator ?! How else am I supposed to do this?
I then found this question here on stackoverflow and all answers say don't use Service Location.
What am I supposed to do?
This seems to be another chapter from the book "Why providers are bad design?". You have the same problem as with any kind of ASP.NET providers. There are no really good and satisfying solutions for them. Just hacks.
I think the best option you have is to fork the project and change the DefaultSiteMapProvider to use DepencencyResolver instead of the Activator and provide the implementation back to the community. Then you can use constructor injection in your PageNodeProvider implementation. This will solve the problem once for all types and everyone.
Of course you could also use the DependencyResolver just in your implementation. But this is by far not the best solution because you should get the instances as close to the root as possible, it makes testing more complicated and it solves the problem just for you.
Even though I see that you've decided to ditch the provider altogether, I'd like to elaborate on using the DependencyResolver. Basically, you can manually get the correct repository instance via Ninject using
var repository = DependencyResolver.Current.GetService<IRepository>();
This is less robust, as you have to maintain this as well as the NinjectMVC3.cs class should the stuff change, and it is a bit more complicated to test.
In a controller, I do the following:
DBContext DB = new DBContext();
var u = DB.Users.Find(1);
u.firstname = "blah";
UpdateModel(u);
DB.SaveChanges();
I want to do the same from within a model...
namespace Project.Models
{
public class User
{
public void resetPassword()
{
// Generate new password, etc.
this.password = "blah";
}
}
}
Any idea how I go about doing this? It seems UpdateModel() is only available from within controllers.
I'm using EntityFramework Code-First CTP5.
I think UpTheCreek is correct but it probably needs some explanation so I'll try to expand on his/her answer. The first step would be to use the repository pattern. You can find many examples of this pattern in MVC with a google search - this is a particularly gentle introduction (about 3/4's down the page).
The walkthrough goes on to mention dependency injection, and that's something that's also worth looking in to. I tend to favor Ninject myself, however there are other dependency injection containers available.
Putting data access concerns in your model is not a good idea.
Update: Yes, you'd usually have a data access layer for this. As Andy says, the currently fashionable way to do this is using a repository. As a rule, you don't want anything in your model that is not core business logic.
In the real world, Controllers can potentially need to use data from a variety of database tables and other data stores. For example:
[Authorize]
public class MembersController : Controller
{
ICourseRepository repCourse;
IUserCourseRepository repUserCourse;
IMember member;
public MembersController(ICourseRepository repCourse, IUserCourseRepository repUserCourse, IMember member)
{
this.repCourse = repCourse;
this.repUserCourse = repUserCourse;
this.member = member;
}
So:
Should I use a repository for each table?
I guess this is where the concept of agregates comes into play? Should I have one Repository per aggregate?
Do I just add as many Repositories as I need to the constructor of the Controller?
Is this a sign that my design is wrong?
NOTE:
The IMember interface essentially represents a helper object that puts a nice face on the Membership provider. Ie, it puts all the code in one place. For example:
Guid userId;
public Guid UserId
{
get
{
if (userId == null)
{
try
{
userId = (Guid) Membership.GetUser().ProviderUserKey;
}
catch { }
}
return userId;
}
}
One problem with that is surely caching this kind of output. I can feel another question coming on.
EDIT:
I'm using Ninject for DI and am pretty sold on the whole DI, DDD and TDD thing. Well, sort of. I also try to be a pragmatist...
1. Should I use a repository for each table?
Probably not. If you have a repository per table, you are essentially doing Active Record. I also personally prefer to avoid calling these classes "Repository" because of the confusion that can occur between Domain Driven Design's concept of a "Repository" and the class-per-table "Repository" that seems to have become commonly used with Linq2SQL, SubSonic, etc. and many MVC tutorials.
2. I guess this is where the concept of agregates comes into play? Should I have one Repository per aggregate?
Yes and yes. If you are going to go this route.
'3.' Do I just add as many Repositories as I need to the constructor of the Controller?
I don't let my controllers touch my repositories directly. And I don't let my Views touch my domain classes directly, either.
Instead, my controllers have Query classes that are responsible for returning View Models. The Query classes reference whatever repositories (or other sources of data) they need to compile the View Model.
Well #awrigley, here is my advise:
Q: Should I use a repository for each table?
A: No, as you mentioned on question 2. use a repository per aggregate and perform the operations on aggregate root only.
Q: Do I just add as many Repositories as I need to the constructor of the Controller?
A: I guess you´re using IoC and constructor-injection, well, in this case, make sure you only pass real dependencies. this post may help you decide on this topic.
(pst! that empty catch is not a nice thing!!) ;)
Cheers!
This all depends on how "Domain Driven Design" your going to be. Do you know what an Aggregate Root is? Most of the time a generically typed repository that can do all your basic CRUD will suffice. Its only when you start having thick models with context and boundaries that this starts to matter.
My web App prepares out of a db for one or two minutes a specific and read-only object list, once only when IIS starts. This does not change any more unless the admin triggers recreation by a specific URL.
The Interface of the objects looks like this:
public interface IProductsRepository {
IQueryable<Row1> ProductItmes { get; }
IQueryable<Row2> ProductLegItems { get; }
}
I am now not really sure where i put the object so it is accessible from any controller.
Should i put the load method to protected void Application_Start() as a static object? What is the best approach?
you need to use a dependency injection framework here so you can instantiate this one and pass it into all of your controllers. This doesn't come out of the box with asp.net-mvc but you can find a number of options that will do the trick like castle windsor or autofac
This may or may not meet your needs but Castle Windsor allows you to specify how many instances a component (like a data repository) will have. I personally had a typo when working with this (lifesyle instead of lifestyle) that resulted in the data repository persisting after a post without my initializing it.
http://www.castleproject.org/container/documentation/trunk/usersguide/lifestyles.html
A good place would be the the Cache. You can load the Cache on Application_Start()
You can store it in Application object, but you should inject it into Controller. You shouldn't reference directly Application object, because this will make your application less testable. I use Ninject (http://ninject.org/) for this purpose.
I'm trying to set up NHibernate in an ASP.NET MVC application using a DDD approach. However, I do get an error when trying to lazy load an objects related entity. Heres how I've structured my application:
Infrastructure layer:
Contains mapping files, repository implementations and a NHibernate bootstrapper to configure and build a session factory.
Heres a repository example:
public class CustomerRepository : ICustomerRepository
{
public Customer GetCustomerById(int customerId)
{
using (var session = NHibernateBootstrapper.OpenSession())
return session.Get<Customer>(customerId);
}
}
Domain layer:
Has simple POCO classes, repository and service interfaces
Application layer:
Contains Service implementations.
Heres a service example:
public class CustomerService : ICustomerService
{
private ICustomerRepository _repository;
public CustomerService(ICustomerRepository repository)
{
_repository = repository;
}
public Customer GetCustomerById(int customerId)
{
return _repository.GetCustomerById(customerId);
}
}
Presentation layer:
Contains the ASP.NET MVC application. And this is where I discovered my problem.
Using the MVC approach, I have a controller which, using the CustomerService service, gets a customer and displays the customer in a View (strongly typed). This customer has a related entity Contact, and when I try to access it in my View using Model.Contact, where Model is my Customer object, I get an LazyInitializationException.
I know why I get this. It's because the session used to retrieve the Customer in the CustomerRepository is dead by now. My problem is how I can fix this. I would like if I could avoid getting the related Contact entity for the Customer in my repository, because some views only need the Customer data, not the Contact data. If this is possible at all?
So to the question: is it possible to wait querying the database, until the presentation layer needs the related entity Contact?
I think that what I need is something like what this article describes. I just can't figure out how to implement it in infrastructure layer, or where should it be implemented?
Thanks in advance. Any help will be much appreciated!
As for session management it is common to use single session per request. You can see an example of implementation here. It is an open source project that were designed to setup new asp.net applications with the help of Nhibernate wery easy. source code can be founded here.
Hope it helps.
I also recommend Sharp Architecture.
Another approach, as well as suggestion, is to avoid passing entities to views. There're other problems with it except session management - business rules leaking into views, bloated/spagetti code in there, etc. Use ViewModel approach.
Another problem you'll get is storing your entities in Session. Once you try to get your Customer from Session["customer"] you'll get the same exception. There're several solutions to this, for example storing IDs, or adding repository methods to prevent lazy-loading of objects you're going to store in session - read NHibernate's SetFetchMode - which, of course, you can also use to pass entity to views. But as I said you better stick with ViewModel approach. Google for ViewModel, or refer to ASP.NET MVC In Action book, which uses samples of code from http://code.google.com/p/codecampserver/. Also read this, for example.
Are all your properties and methods in your Customer class marked virtual?
How are you opening and closing your session? I use an ActionFilterAttribute called TransactionPerRequest and decorate all my controllers with it.
Check out this for an implementation.