Fluent NHibernate pattern for both IHttpModule and

2019-05-11 02:02发布

问题:

I currently have a C# MVC 2 web app using Fluent NHibernate (+ LINQ) in a Repository Pattern and am using Ninject to handle the MVC controller's constructor requirement that it be passed in the repository.

My Fluent NHibernate code is currently hooked into an IHttpModule, so the session can be opened and closed with the web request.

This works great until I try to hook my domain model into a console app.

First, I decided to move my database logic into my domain model. I'm guessing this is bad behavior but I am here asking for help on code design, so please feel free to make suggestions. I wanted to do this because I want to write a console app + web app on this domain model without caring where or how the data is stored. Perhaps I should have a separate "Infrastructure" project that uses the domain model to do a particular implementation?

Getting back to the question ... I run into a problem where it seems Fluent NHibernate's GetCurrentSession() assumes you're using the web - it crashes and I get a traceback to some NH code mentioning a WebSession.

For reference sake, the code is here: https://github.com/cthielen/RightsManagement .

My apologies for not being too specific; I'm looking for code design advice to best handle FNH + Linq in a repository pattern that works well both with the Web and a console app -- and separately asking if my database connection (i.e. NH logic) should be in the domain project or not.

回答1:

This is a good question. There are a lot of different ways that this could be answered, but each answer is going to depend on how much experience you have with the different approaches out there. For example, are you familiar with TDD? Dependency injection? IoC containers? And so on.

The best advice I can give at this point is to clean up all of your existing classes so that they are not context dependent. One example of this would be modifying your repository classes so that they take an ISession object as a constructor argument instead of depending on what appears to be a singleton instance that only exists if you're in a HTTP context. This would allow you to refactor the session creation logic to a higher level outside of your domain logic.

public class PeopleRepository {
    public PeopleRepository(ISession session) {
        // store session
    }
}

In my case, I would use a IoC container to inject the session dependency. I can use this container from any type of application, whether it's a web based application using the session-per-request pattern or a console application.

There's some work you'll need to do to get NHibernate to play nice in both applications. The challenge is to minimize that work as much as possible.

I'm happy to provide more guidance. Let me know.



回答2:

I often use a session object to indicate that I'm going to work with something (It's not a Unit Of Work implementation since I do not save all work until a certain point)

using (var session = SessionFactory.Create())
{
   // do all work here
}

This works since even console applications have a starting point in which the session can be initiated (for instance when the user have written a command in the console).

The session factory has a SessionCreated and a SessionDestroyed event which can be hooked by anything, in our case a nhibernate session factory.

It's a nice abstracted way to get support for a database connection or whatever without using hard dependencies