649
I Use This!
Moderate Activity

News

Analyzed about 13 hours ago. based on code collected 1 day ago.
Posted over 12 years ago by felicepollano
Even if Linq To NHibernate provider allow us to write query in a strongly type manner, it is sometimes needed to works with property names literally. For example in a RIA application a service can receive a column as a string containing the name of ... [More] the property to order by. Since Linq to NHibernate is a standard Linq provider, we can leverage a standard dynamic linq parser. This is achieved by using an old code by MS, known as System.Linq.Dynamic. By following the link you will find a download location that point to an almost just a sample project that eventually contains the file Dynamic.cs that contains some extension method allowing to merge literal parts in a type safe linq query. Let’see an example: var elist = session.Query<MyEntity>() .OrderBy(“Name descending”) .Skip(first) .Take(count) .ToList(); I supposed we have a property called Name on the class MyEntity. The OrderBy taking a string as a parameter is an extension method provided by Dynamic.cs, and in order to have it working you just need to merge the file dynamic.cs in your project and import System.Linq.Dynamic. Of course you will have extension for Where and for other linq operators too. ( cross post from my blog ) [Less]
Posted over 12 years ago by Billy McCafferty
[The motivations for releasing S#arp Lite, in relation to S#arp Architecture, are described here.] What is S#arp Lite? S#arp Lite is an architectural framework for the development of well-designed, custom-built, ASP.NET MVC applications using ... [More] NHibernate for data access. ASP.NET MVC 3 is a terrific platform for delivering web-based applications.  But, similar to ASP.NET, it does not provide specific guidelines for how to best use it in different project contexts.  That's certainly the point; it exists to provide a flexible platform which may be used in a variety of situations without being biased towards one architecture or another, beyond the fundamentals of Model-View-Controller.  The benefit of this is that you can structure MVC projects almost anyway you'd like; the drawback is that it's possible to have almost no consistency among your organization's projects, even if they're all using ASP.NET MVC. That's where S#arp Lite comes in to play.  S#arp Lite comes packaged with three primary assets to provide a turnkey solution for developing well-designed, MVC applications: A project template to facilitate the creation of new S#arp Lite projects, pre-configured to communicate with your database using NHibernate; A set of reusable class libraries which encapsulates infrastructural concerns (including a base repository); and  Architectural guidance on how to build out a S#arp Lite project. Currently, the architectural guidance is demonstrated via the sample project which has been included in the S#arp Lite release package.  Architectural guidelines are also enforced by the direction of dependencies among the project layers.  (This will be discussed in more detail below.) The overall objective is to allow your development team to more easily develop ASP.NET MVC applications which adhere to well founded principles, such as domain-driven design and test-driven development; without being bogged down with infrastructural setup and without sacrificing long-term maintainability and scalability of the solution. As a quick side, the base repository class which S#arp Lite exposes is purposefully very simplistic.  The base repository only includes the following methods: Get(id):  returns an entity from the database having the Id provided, GetAll():  returns an IQueryable<> which may be further filtered/transformed via LINQ, SaveOrUpdate(entity):  persists an entity to the database, and Delete(entity):  deletes an entity from the database. Keeping the base repository very light has greatly reduced bloat and places greater emphasis on the use of LINQ for retrieving results from GetAll().  We'll discuss this in more detail a bit later. Who is this intended for? The motivation for S#arp Lite came from working with many teams (including my own) who had been developing projects with S#arp Architecture.  To many, S#arp Architecture is simply too big of an architectural framework to easily get your head.  When I used to discuss S#arp Architecture with teams who were considering using it, I would always suggest that their developers be very experienced and well versed with topics such as dependency inversion, low-level NHibernate, and domain-driven design. The reality of business is that it's not likely that your team will be made up of all senior level developers who are all experts in these topics.  S#arp Lite is intended to epitomize the underlying values of S#arp Architecture, strive to be equally scalable to larger projects, all while being tenable to a larger audience.  In other words, you should be able to have a realistically skill-balanced team and still be able to successfully deliver a S#arp Lite application. S#arp Lite is recommended for any mid-to-large sized ASP.NET MVC project.  If you have a small mom & pop store, you'd likely be better off using a less-tiered application setup.  It scales well to very large projects.  We're using it effectively on for applications which integrate with a half dozen other systems...so it certainly holds up to larger tasks as well. What does a S#arp Lite project look like? Creating a new S#arp Lite project is trivially simple: Download and unzip the S#arp Lite release package from GitHub. Follow the instructions within the README.txt to creation your S#arp Lite project with Templify (a brilliant little tool). After you've created a S#arp Lite project, you'll find the following directory structure under the root folder: app:  This folder holds the source of the project; i.e., the code that you're getting paid to write. build:  This initially empty folder is a placeholder for your build-related artifacts, such as your "publish" folder, NAnt or MSBuild artifacts, etc. docs:  This initially empty folder contains all of the documents for your project.  Keeping them here keeps all of your docs checked in with the code. lib:  This folder contains all of the DLL dependencies for your project, such as log4net.dll, SharpLite.Domain.dll, System.Web.Mvc.dll, etc. logs:  This initially empty folder is intended to hold any generated log files.  The generated project's web.config used this folder for dumping out log4net logs. tools:  This initially empty folder is intended to hold any third party install files or other dependencies which the team may need to work on the project.  For example, this is where we store the latest installation of Telerik ASP.NET MVC and NUnit, used by the project.  Having all of your installable dependencies, checked in with the code, makes it much easier to get "the new guy" up and running quickly. The auto-generated folder structure is just a means to help keep your digital assets and solution files organized.  The more interesting stuff is in the /app folder which houses the source code of the solution.  Before we delve into the projects included in a S#arp Lite project, let's take a birds eye view of the overall architecture. The diagram above reflects the layers of a S#arp Lite project, implemented as separate class libraries and an ASP.NET MVC Web Project.  Having the tiers in separate class libraries allows you to enforce the direction of dependency among them.  For example, because YourProject.Tasks depends on YourProject.Domain, YourProject.Domain cannot have any direct dependencies on a calss within YourProject.Tasks.  This singled-directional dependency helps to enforce how the architecture is to remain organized. While the diagram above describes the basic purpose of each layer, it's most assistive to look at an example project to have a clearer understanding of the scope of responsibilities of each layer.  Accordingly, let's examine the tiers of the MyStore example application which was included in the S#arp Lite release package. Examining the Layers of MyStore Sample Application The MyStore sample application, included in the release zip, demonstrates the use of S#arp Lite for a fairly typical CRUD (create/read/update/delete) application.  It includes managing data and relationships such as one:one, one:many, many:many, and parent/child.  Let's take a closer look at the relational model. The diagram above represents the relational object model, as implemented within a SQL Server database.  It's a very simple model with basic relationships, but it still brings up a lot of interesting discussion points when we go to translate this relational model into the object-oriented design of our application. For example, each customer entity contains address information (stored as StreetAddress and ZipCode in the Customers table); in the domain, we want the address information pulled out into a separate object called Address.  Having this information as a separate object more easily allows us to add behavior to the Address object while keeping those concerns separate from the Customer object, such as integration with a USPS address validation service.  (Arguably, such a service would be in a stand-alone service class, but you get the idea.) As another example, the many:many Products_ProductCategories table shouldn't have a similarly named class in our object model; instead, we would expect Products to have a listing of ProductCategories and/or vice-versa. The sample application includes examples of how all of this and mappings of the classes themselves have been achieved almost entirely via coding-by-convention.  Let's now look at the sample application, layer-by-layer, and interesting points along the way. MyStore.Domain This layer of the application contains the heart of the application; it represents the core domain of our product.  All the other layers exist simply to support the user's need to interact with the domain.  In a S#arp Lite project, the domain layer contains four types of objects: Domain Objects Query Objects Query Interfaces Custom Validators Let's review each in turn. Domain Objects Alright, so maybe this is a whole bunch of types of objects, but they all have the same purpose - they exist to implement the domain of our application.  They consist of entities, value objects, services (e.g., calculators), factories, aggregates...all organized into modules, usually expressed as separate namespaces.  (I highly recommend Eric Evans' Domain-Driven Design, Jimmy Nilsson's Applying Domain Driven Design and Patterns, and Agile Software Development by Robert Martin to help guide you.)  There are two namespaces in the sample project:  the "ProductMgmt" namespace which contains everything related to product management, and the "root" namespace for, well, everything else.  Your project will likely have others. Let's now take a look at the Customer class within the sample project as an example of an entity.  There are some important items to note: Customer inherits from Entity (which is from SharpLite.Domain.dll).  The Entity base class A) signals that this class is a persisted object which has an associated table in the database, B) provides an Id property (no biggie there), and C) facilitates comparing two entities to each other.  If two entities are of the same type and have the same Id, then you know they're the same object.  But what if you're comparing two "transient" entities; i.e., two entities which have not yet been persisted to the database.  As another example, how would you go about comparing a transient entity to entities that have been persisted.For this we need to compare "domain signatures."  A domain signature is the fingerprint of what makes the entity unique from a business perspective.  In other words, which property(s) of an object would make it identifiable without having an Id property?  Looking at the Customer class, we see that there are two properties decorated with the attribute "DomainSignature."  Furthermore, the class itself is decorated with the attribute "HasUniqueDomainSignature."  This means that no two objects may exist having the same first and last name.  (This will not be appropriate in all scenarios; but should reflect the domain signature of the object in the context of the application.)  The described attributes are included in SharpLite.Domain.dll and support automatic validation of the class' domain signature.  So if you try to add a new customer with the same first and last name as an existing customer, a validation message will let you know this is not allowed. [HasUniqueDomainSignature(... public class Customer : Entity { [DomainSignature] ... public virtual string FirstName { get; set; }   The Customer class pulls encapsulates the address information from the Customers table into a separate Address class.  Interestingly, NHibernate "loquacious" mapping (aka - code by convention) automatically maps the related table columns into this "component" object. Customer has an IList of Orders with a protected setter; the collection is initialized in the constructor.  This is done for two reasons:  1) by design, the collection will never be null (which avoids a lot of object reference exception avoidance), and 2) we don't have to worry about NHibernate losing its pointer to the original collection loaded from the database.  This collection "pattern" is simply good practice for exposing/protecting the collection. public class Customer : Entity { public Customer() { Orders = new List(); } public virtual IList Orders { get; protected set; } Validation is enforced with standard, .NET data annotations.  No need for NHibernate.Validator or other validation mechanism when it's all available via the .NET library.  And whenever you run into limitations, you can simply create a custom validator. Query Objects Regularly, we need to filter information returned from the database.  For example, we may just want to return "active" customers vs. all the customers in the database.  For performance reasons, it's obviously better to put as much filtering work on the shoulders of the database.  Before LINQ providers, it was difficult to find the appropriate balance between filtering on the domain side or filtering on the database side.  But with LINQ and IQueryable, filtering can be developed within the domain while it's still executed on the database.   Brilliant!  To facilitate this, every repository (e.g., IRepository<Customer>) exposes the method GetAll() which returns IQueryable<>. The abso-friggin-spectacular side effect of this is that we can avoid having specialty "repository" methods which exist simply to hide away the details of the underlying data-access mechanism.  There are two kinds of query objects in a S#arp Lite project: Specification Query Objects:  Specification query objects take a list and filter the results down to a smaller list, based on some criteria.  In the sample project, the specification query class, MyStore.Domain.FindActiveCustomers, provides an extension method to IQueryable<> with any filter parameters passed in to the method.  Alternatively, the query object could be a POCO class, accepting an IQueryable<> and filtering, accordingly.  The benefit to setting up the specification query object as an extension, albeit, with additional indirection, is that multiple queries may be chained, all while taking advantage of IQuerable<>'s delayed querying (i.e., only one query will be sent to the database even if you chain multiple queries. public static class FindActiveCustomersExtension { public static IQueryable FindActiveCustomers(this IQueryable customers) { return customers.FindActiveCustomers(MINIMUM_ORDERS_TO_BE_CONSIDERED_ACTIVE); } public static IQueryable FindActiveCustomers(this IQueryable customers, int minimumOrders) { return customers.Where(c => c.Orders.Count >= minimumOrders); } private const int MINIMUM_ORDERS_TO_BE_CONSIDERED_ACTIVE = 3; } To me, the real beauty in this is that the query object may live in the domain, and be tested as a first class citizen of the domain, without introducing any dependencies to the underlying data-access layer (whether that be NHibernate, Entity Framework, etc.).    Report Query Objects:  Report query objects take a list, filtering if necessary, transforming and returning the results as a DTO or list of DTOs.  Imagine that you have a summary dashboard in your application; e.g., a page which shows how many orders each customer has placed and what is each customer's most frequently purchased product.  In this scenario, we'd ultimately like a list of DTOs containing each customer's name, his/her order count, and his/her favorite product.  There are a few options to tackling this: Create a DB stored procedure, binding the results to the DTOs list (and thus put processing logic onto the DB), Use NHibernate Criteria, HQL or named query to retrieve the results (and tightly couple your data-access code to NHibernate), Traverse the object model on the domain side to collate the information (can you say n+1?), or Use clean and simple, data-access agnostic LINQ (and keep it in the domain). 2 points if you guess which one I'm leaning towards. Let's look MyStore.Domain.Queries.QueryForCustomerOrderSummariesExtension for an example: public static class QueryForCustomerOrderSummariesExtension { public static IQueryable QueryForCustomerOrderSummaries(this IQueryable customers) { return from customer in customers select new CustomerOrderSummaryDto() { FirstName = customer.FirstName, LastName = customer.LastName, OrderCount = customer.Orders.Count }; } } Again, the advantage of this is that it can live within the domain layer and act as a reusable reporting query without introducing dependencies to the underlying data-access layer. You have a lot of flexibility on how you use query objects and where they live.  For example, you could use an ad-hoc report query (i.e., a LINQ query not encapsulated by a class) which lives within a method in the tasks layer.  Although I'd advise against it, you could even use an ad-hoc query within a controller's method.  So the provided samples are just that, samples of a particular approach.  What's most important is to agree as a team how you'll encapsulate and organize query objects.  In the sample project, queries are encapsulated as query objects and stored within a "Queries" folder - one folder per namespace. Query Interfaces In the very unlikely event that you need to leverage the data-access mechanism directly, instead of LINQing IQueryable, the domain layer may also contain any query interfaces which define a query to be implemented by the data-access layer.  (This is akin to creating custom repository interfaces in S#arp Architecture.) The disadvantages to this approach are three-fold: It introduces a layer of indirection to the developer, It more tightly couples your code to the underlying data-access layer (since some of your application's logic is now in the data-access layer), and It becomes trickier to unit test the query since you need an in-memory or live database to test the implementation. But, I can foresee that there may be a situation where this is necessary if you have a very complicated query, need to leverage NHibernate detached queries, or simply can't do what needs to be done via LINQ.  Accordingly, three steps would need to be taken to support the query: Define the query interface in YourAppProject.Domain (e.g., MyStore.Domain.ProductMgmt.Queries.IQueryForProductOrderSummaries.cs), Implement the concrete query class in YourAppProject.NHibernateProvider (e.g., MyStore.NHibernateProvider.Queries.QueryForProductOrderSummaries.cs), and Register the implementation with the IoC to resolve requests to the interface (e.g., MyStore.Init.DependencyResolverInitializer). Obviously, not as clean as using Specification and Report Query Objects, but available if absolutely necessary. Custom Validators As discussed previously, S#arp Lite uses .NET's data annotations for supporting validation.  (You could use something else, like NHibernate.Validator if you prefer.)  The data annotations are added directly to entity classes, but could instead be added to form DTOs if you feel that entities shouldn't act as form validation objects as well. Sometimes, data annotations aren't powerful enough for the needs of your domain; e.g., if you want to compare two properties.  Accordingly, you can develop custom validators and store them within a "Validators" folder.  If the custom validator is specific to a class, and never reused, then I'll usually just add the custom validator class as a private subclass to the class which uses it.  In this way, the class-specific validator is neatly tucked away, only accessible by the class which needs it.  S#arp Lite uses a custom validator to determine if an object is a duplicate of an existing object, using its domain signature:  \SharpLiteSrc\app\SharpLite.Domain\Validators\HasUniqueDomainSignatureAttribute.cs. MyStore.Tasks This layer of the application contains the task-coordination logic, reacting to commands sent from, e.g., a controller in the presentation layer.  (This layer is also described as a Service Layer in Martin Fowler's PoEAA.)  For example, let's assume that your application integrates with a number of other applications.  This layer would communicate with all of the other applications (preferably via interfaces), collating the information, and handing it off to the domain layer for performing domain logic on the data.  As a simpler example, if your domain layer contains some kind of FinancialCalculator class, the tasks layer would gather the information needed by the calculator, from repositories or other sources, and pass the data via a method to FinancialCalculator. As a secondary responsibility, the tasks layer returns data, as view-models, DTOs, or entities, to the presentation layer.  For example, the presentation layer may need to show a listing of customers along with Create/Edit/Delete buttons if the logged in user has sufficient rights to do so.  The tasks layer would get the listing of customers to show and would determine what security access the user has; it would then return a view model containing the customers listing along with a bool (or security object) describing if the user has rights to modify the data. It's important to note the difference between the logic found within the tasks layer and that found within the domain layer.  The tasks layer should contain minimal logic to coordinate activities among services (e.g., repositories, web services, etc.) and the domain layer (e.g., calculator services).  Think of the tasks layer as an effective boss (does that exist?)...the boss helps to facilitate communications among the team and tells the team members what to do, but doesn't do the job itself. The tasks layer contains two kinds of objects: Task Objects View Models Task Objects These are the tasks themselves.  The most common kind of task is coordinating CUD logic (CRUD without the read).  It's so common, in fact, that S#arp Lite projects includes a (completely customizable) BaseEntityCudTasks class to encapsulate this common need.  Looking at the sample project, you can see how BaseEntityCudTasks is extended and used; e.g., within MyStore.Tasks.ProductMgmt.ProductCudTasks. As the project grows, the task-layer responsibilities will inevitably grow as well.  For example, on a current project which integrates with multiple external applications, a task class pulls schedule information from Primavera 6, cost information from Prism, and local data from the database via a repository.  It then passes all of this information to a MasterReportGenerator class which resides in the domain.  Accordingly, although the task class is non-trivial, it's simply pulling data from various sources, leaving it up to the domain to the heavy processing of the data. It's important to note that a task object's service dependencies (repositories, web services, query interfaces, etc.) should be injected via dependency injection.  This facilitates the ability to unit test the task objects with stubbed/mocked services.  With MVC 3, setting up dependency injection is very simple and makes defining your task objects dependencies a breeze: public ProductCategoryCudTasks(IRepository<ProductCategory> productCategoryRepository) : base(productCategoryRepository) { _productCategoryRepository = productCategoryRepository; } Here we see that the ProductCategoryCudTasks class requires a IRepository<ProductCategory> injected into it, which will be provided at runtime by the IoC container or by you when unit testing. View Models A view model class encapsulates information to be shown to the user.  It doesn't say how the data should be displayed, only what data should be displayed.  Frequently, it'll also include supporting information for the presentation layer to then decide how the information is displayed; e.g., permissions information. There's a lot of debate about where view model classes should reside.  In my projects, I keep them in the tasks layer, with one ViewModels folder per namespace.  But arguably, view model classes could live in a separate class library; that's for your team to decide at the beginning of a project. MyStore.Web There's not much to say here.  A S#arp Lite project uses all out-of-the-box MVC 3 functionality for the presentation layer, defaulting to Razor view engines, which you may change if preferred.  The only S#arp Lite-isms (totally a word) in this layer are as follows: MyStore.Web.Global.asax invokes DependencyResolverInitializer.Initialize(); to initialize the IoC container (discussed below), MyStore.Web.Global.asax uses SharpModelBinder to act as the preferred form/model binder, and Web.config includes an HttpModule to leverage a session-per-request, NHibernate HTTP module, found within the S#arp Lite source at \SharpLiteSrc\app\SharpLite.NHibernateProvider\Web\SessionPerRequestModule.cs. SharpModelBinder extends the basic form/model binding with capabilities to populate relationships.  For example, suppose you have a Product class with a many:many relationship to ProductCategory.  When editing the Product, the view could include a list of checkboxes for associating the product with one or more product categories.  SharpModelBinder looks for such associations in the form and populates the relationships when posted to the controller; i.e., the Product which gets posted to the controller will have its ProductCategories populated, containing one ProductCategory for each checkbox that was checked.  You can take a look at MyStore.Web/Areas/ProductMgmt/Views/Products/Edit.cshtml as an example. Like task objects, controllers also accept dependencies via injection; e.g. MyStore.Web.Areas.ProductMgmt.Controllers.ProductsController.cs: public ProductsController(IRepository<Product> productRepository, ProductCudTasks productMgmtTasks, IQueryForProductOrderSummaries queryForProductOrderSummaries) { _productRepository = productRepository; _productMgmtTasks = productMgmtTasks; _queryForProductOrderSummaries = queryForProductOrderSummaries; } In the example above, the controller requires an instance of IRepository<Product>, ProductCudTasks, and IQueryForProductOrderSummaries passed to its constructor from the IoC container.  IQueryForProductOrderSummaries is an example of using a query interface, defined in the domain, for providing data-access layer specific needs.  It's a very exceptive case and has only been included for illustrive purposes.  You'd almost always be able to use specification and report query objects instead...or simply LINQ right off of IRepository<Product>.GetAll(). If you'd like to learn more about dependency injection in ASP.NET MVC 3, check out Brad Wilson's series of posts on the subject.  And for learning more about the basics of developing in the web layer, Steve Sanderson's Pro ASP.NET MVC 3 Framework is a great read. MyStore.Init This nearly anemic layer has one responsibility:  perform generic, application initialization logic.  Specifically, the initialization code included with a S#arp Lite project initializes the IoC container (StructureMap) and invokes the initialization of the NHibernate session factory.  Arguably, this layer is so thin that its responsibilities could easily be subsumed by MyStore.Web.  The great advantage to pulling the initialization code out into a separate class library is that MyStore.Web requires far fewer dependencies.  Note that MyStore has no reference to NHibernate.dll nor to StructureMap.dll.  Accordingly, there is very little coupling (i.e., none) to these dependencies from the web layer...we like that.  Among other things, this prevents anyone from invoking an NHibernate-specific function from a controller.  This, in turn, keeps the controllers very decoupled from the underlying data-access mechanism as well. MyStore.NHibernateProvider The next stop on our tour of the layers of a S#arp Lite project is the NHibernate provider layer.  With S#arp Architecture, this layer would frequently get quite sizable with custom repositories and named queries.  With the alternative use of query objects and LINQ on IQueryable<>, this class library should remain very thin.  This class library contains three kinds of objects: NHibernate Initializer, NHibernate Conventions, Mapping Overrides, and (very occasionally) Query Implementations. Let's look at each in turn. NHibernate Initializer NHibernate 3.2.0 introduces a built-in fluent API for configuration and mapping classes, nicknamed NHibernate's "Loquacious" API.  This is a direct affront to Fluent NHibernator which (as much as I have truly loved it...a sincere thank you to James Gregory) I feel is headed for obsolescence with these capabilities now being built right in to NHibernate.  NHibernate 3.2's Loquacious API isn't yet as powerful as Fluent NHibernate, but will get there soon as more of ConfORM is ported over to Loquacious API.  On with the show... There is one NHibernate initialization class with a S#arp Lite project; e.g., MyStore.NHibernateProvider.NHibernateInitializer.cs.  This class sets the connection string (from web.config), sets the dialect, tells NHibernate where to find mapped classes, and invokes convention setup (discussed next).  Initializing NHibernate is very expensive and should only be performed once when the application starts.  Accordingly, take heed of this if you decide to switch out the IoC initialization code (in MyStore.Init) with another IoC container. NHibernate Conventions The beauty of conventions is that we no longer need to include a class mapping (HBM or otherwise) for mapping classes to the database.  We simply define conventions, adhere to those conventions, and NHibernate knows which table/columns to go to for what.  S#arp Lite projects come prepackaged with the following, customizable conventions: Table names are a plural form of the entity name.  E.g., if the entity is Customer, the table is Customers. Every entity has an Id property mapped to an "Id" identity column (which can easily be changed to HiLo, Guid, or otherwise). Primitive type column names are the same name as the property.  E.g., if the property is FirstName, the column name is FirstName. Foreign keys (associations) are the name of the property suffixed with "Fk."  E.g., if the property is Order.WhoPlacedOrder, the column name (in the Orders table) is WhoPlacedOrderFk with a foreign key to the respective type's table (e.g., Customers). There is typically just one convention-setup class in a S#arp Lite project; e.g., MyStore.NHibernateProvider.Conventions.  The only convention that isn't supported "out of the box" is a many:many relationship, which we'll discuss more below. Mapping Overrides There are times when conventions don't hold up.  Examples include: Many-to-many relationships, Enum as a property type,  Legacy databases which don't stick to (your) conventions, and  Anytime a convention is not followed for one reason or another. On the upside, this isn't too many cases...but we need to be able to handle the exceptions.  Any exceptions to the conventions are defined as "mapping overrides."  Examples of overrides may be found in MyStore.NHibernateProvider/Overrides.  To make things easy, if an override needs to be added, simply implement MyStore.NHibernateProvider.Overrides.IOverride and include your override code.  The MyStore.NHibernateProvider.Conventions class looks through the assembly for any classes which implements IOverride and applies them in turn.  As a rule, I create one override class for each respective entity which requires an override. Query Implementations Lastly, the .NHibernateProvider layer contains any NHibernate-specific queries, which are implementations of respective query interfaces defined in the .Domain layer.  97.6831% of the time, this will not be necessary as querying via LINQ, off of IQueryable<>, is the preferred approach to querying.  But in the rare case that you need to implement a query using NHibernate Criteria, HQL, or otherwise, this is the layer to house it.  A sample has been included as MyStore.NHibernateProvider.Queries.QueryForProductOrderSummaries. MyStore.Tests At the end of our tour of the layers of a S#arp Lite project is the .Tests layer.  This layer holds all of the unit tests for the project.  S#arp Lite projects are generated with two unit tests out of the box: MyStore.Tests.NHibernateProvider.MappingIntegrationTests.CanGenerateDatabaseSchema():  This unit tests initializes NHibernate and generates SQL to reflect those mappings.  This is a great test to run to verify that a class is being mapped to the database as expected; i.e., you can look at the generated SQL (in the Text Output tab in NUnit) to verify how a class is being mapped.  As a side-benefit, you can copy the generated SQL and run it to make modifications to the database.  Finally, the unit tests saves the generated SQL into /app/MyStore.DB/Schema/UnitTestGeneratedSchema.sql for additional reference. MyStore.Tests.NHibernateProvider.MappingIntegrationTests.CanConfirmDatabaseMatchesMappings():  This unit tests initializes NHibernate and verifies that every entity maps successfully to the database.  If you have a missing column, this test will let you know.  It doesn't test everything, such as many-to-many relationships, but certainly 97.6831% of everything else. For an introduction to test-driven development, read Kent Beck's Test Driven Development: By Example.  Going a step further, go with Gerard Meszaros' xUnit Test Patterns and Michael Feathers' Working Effectively with Legacy Code. In S#arp Architecture, SQLLite was used to provide an in-memory database for testing custom repository methods.  Since custom repositories have been mostly relegated to obsolescence, keeping SQLLite testing built-in to S#arp Lite would have been overkill and has been removed to keep things simpler.  (Besides, you can always look at the S#arp Architecture code for that functionality if needed.) What's in the S#arp Lite Libraries? Most of what's relevant in the S#arp Lite class libraries has already been discussed while going through the sample project, but let's take a moment to see what all is in the reusalbe, S#arp Lite class libraries. SharpLite.Domain This class library provides support for the domain layer of your S#arp Lite project. ComparableObject.cs:  Provides robust, hash code generator for any object which inherits from it.  (It's much trickier to implement than you think. ;) DomainSignatureAttribute.cs:  An attribute used to decorate properties which make up a class' domain signature. EntityWithTypedId (defined in Entity.cs):  Provides a (non-mandatory) generic base class for your entities, including an Id property and the inclusion of domain signature properties when comparing like objects.  It takes a single, generic parameter declaring the type of the Id property; e.g., int or Guid. Entity.cs:  Provides an EntityWithTypedId base class with an Id assumed to be of type int. IEntityWithTypedId.cs:  Provides an interface which may be used to implement your own entity base class. /DataInterfaces/IDbContext.cs:  Exposes an interface for controlling transactions. /DataInterfaces/IEntityDuplicateChecker.cs:  Exposes an interface for checking if an entity is a duplicate of one already in the database. /DataInterfaces/IRepository.cs:  Exposes a very basic repository including Get, GetAll (returning IQueryable), SaveorUpdate, and Delete. /Validators/HasUniqueDomainSignatureAttribute.cs:  An attribute which may be used to decorate a class to ensure that duplicates do not exist in the database having the same domain signature. SharpLite.EntityFrameworkProvider The idea of this library is to provide a pluggable replacement for the NHibernateProvider (discussed next), if the team so chooses.  This library has not been fully developed yet.  Let me know if you're interested in contributing with this effort. SharpLite.NHibernateProvider This infrastructural class library provides everything necessary for S#arp Lite projects to communicate with the database via NHibernate. DbContext.cs:  Implements IDbContext for transaction management. EntityDuplicateChecker.cs:  Implements IEntityDuplicateChecker for checking for entity duplicates. LazySessionContext.cs:  Supports NHibernate open-session-in-view; originally written by Jose Romaniello. Repository.cs:  Provides a minimalist base repository...feel free to extend as needed. /Web/SessionPerRequestModule.cs:  Provides the HTTP module in support of NHibernate open-session-in-view. SharpLite.Web This class library provides MVC-specific needs for S#arp Lite projects...which consists entirely of SharpModelBinder.cs.  This may be viewed as completely optional for your use in S#arp Lite projects. /Mvc/ModelBinder/EntityCollectionValueBinder.cs:  Used by SharpModelBinder for translating a collection of inputs from the form into a collection of entities bound to the containing object. /Mvc/ModelBinder/EntityRetriever.cs:  Used by SharpModelBinder related classes for retrieving an entity from the database without knowing which repository to use a priori. /Mvc/ModelBinder/EntityValueBinder.cs:  Used by SharpModelBinder for translating a drop-down selection into an entity association bound to the containing object. /Mvc/ModelBinder/SharpModelBinder.cs:  Extends the ASP.NET MVC model binder with additional capabilities for populating associations with entities from the database.   Well, that's it in a nutshell for now.  I sincerely hope that S#arp Lite will prove helpful to you and your team in developing well-designed, maintainable ASP.NET MVC applications that scale well as the project evolves.  This architectural framework reflects lessons learned from years of experience blood, sweat, & tears and countless ideas shamelessly stolen from those much smarter than I. Enjoy!Billy McCaffertyhttp://devlicio.us/blogs/billy_mccafferty  [Less]
Posted over 12 years ago by felicepollano
Note: this is a cross post from my own blog. This post is an exercise, similar to this and this previous posts about using NHibernate  mapping by code new features present form version 3.2. The source inspiring it is an old post form Ayende, showing ... [More] a non trivial requirement to map. Here the DB model: And the wanted object model: So there is a lot of comments about DB refactoring needing, or on needing to have the linking entity as a visible entity in the model, but: I like the idea of collapsing the linking entity. I suppose that the DB is untouchable, as frequently happens. Ayende solves the trouble by the <join/> mapping having an entity spawning two tables, so Address will be represented by joining the Table Address and PeopleAddress. This can be done very easily in Mapping by code too, lets see how:   ModelMapper mapper = new ModelMapper(); mapper.Class<Person>(m => { m.Id(k => k.Id,g=>g.Generator(Generators.Native)); m.Table("People"); m.Property(k => k.Name); m.Bag(k => k.Addresses, t => { t.Table("PeopleAddresses"); t.Key(c=>c.Column("PersonId")); t.Inverse(true); } ,rel=>rel.ManyToMany(many=>many.Column("AddressId")) ); } ); mapper.Class<Address>(m => { m.Id(k => k.Id, g => g.Generator(Generators.Native)); m.Table("Addresses"); m.Property(p => p.City); m.Join("PeopleAddresses", z => { z.Property(p => p.IsDefault); z.Key(k => k.Column("PersonId")); }); m.Join("PeopleAddresses", z => z.Property(p => p.ValidFrom) ); m.Join("PeopleAddresses", z => z.Property(p => p.ValidTo)); } ); That yield  the following mapping: <?xml version="1.0" encoding="utf-16"?> <hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" namespace="TestMappingByCode" assembly="TestMappingByCode" xmlns="urn:nhibernate-mapping-2.2"> <class name="Person" table="People"> <id name="Id" type="Int32"> <generator class="native" /> </id> <property name="Name" /> <bag name="Addresses" table="PeopleAddresses" inverse="true"> <key column="PersonId" /> <many-to-many class="Address" column="AddressId" /> </bag> </class> <class name="Address" table="Addresses"> <id name="Id" type="Int32"> <generator class="native" /> </id> <property name="City" /> <join table="PeopleAddresses"> <key column="PersonId" /> <property name="IsDefault" /> <property name="ValidFrom" /> <property name="ValidTo" /> </join> </class> </hibernate-mapping>   Exactly the ones that Ayende proposed. As you can see is pretty straightforward map even a not so common situation. [Less]
Posted over 12 years ago by felicepollano
Note: this is a cross post from my own blog. In this post we done some effort in automatically generate the mapping based on convention, but we miss a very common one: table names is usually the pluralized entity name. This is usually done by using ... [More] an inflector. Thanks to Stack Overflow, I found this question about it, and choose that one, that is a single easily embeddable file. So we modify a little our AutoMapper class as below: void AutoMapper_BeforeMapClass(IModelInspector modelInspector, Type type, IClassAttributesMapper classCustomizer) { // // Create the column name as "c"+EntityName+"Id" // classCustomizer.Id(k => { k.Generator(Generators.Native); k.Column("c" + type.Name + "Id"); } ); classCustomizer.Table(Inflector.Pluralize(type.Name)); }   And this is all, the generated mapping will change as: <hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="" sd="http://www.w3.org/2001/XMLSchema" namespace="MappingByCode" assembly="Mappin gByCode" xmlns="urn:nhibernate-mapping-2.2"> <class name="SimpleEntity" table="SimpleEntities"> <id name="Id" column="cSimpleEntityId" type="Int32"> <generator class="native" /> </id> <property name="Description"> <column name="txtSimpleEntityDescr" sql-type="AnsiString" /> </property> <many-to-one name="Referred" column="cReferredId" /> </class> … Just for better sharing, I published this “laboratory” project here. [Less]
Posted over 12 years ago by felicepollano
Note: this is a cross post from my own blog. Since version 3.2.0 NHibernate  has an embedded strategy for mapping by code, that basically comes from Fabio Maulo’s ConfORM. With some reading at this Fabio post,  this other one, and this one too, I ... [More] wrote my own sample just to see what we can do. Even if we can use mapping by code to map class by class the entire model, something more interesting can be done by writing some convention-based automatic mapper, that can help us even when we face legacy ( non code first ) databases with some (perverted) naming convention. We have to consider first the ModelMapper class, this class in the NH mapping by code is the one responsible for driving the mapping generator. It provides a suite of events to intercept the actual generation of each elements in the mapping. By listening these event we can decorate the detail of the single element, for example the Id generator class, the SqlType, the column name, and so on. ModelMapper uses a ModelInspector to get the way we want to map each portion of the entity ( properties, many-to-one, collections ), or if we have a component, or a subclass and so on. We realize our AutoMapper class by deriving a ModelMapper and internally subscribing some events, and passing to it a custom ModelInspector ( we named it AutoModelInspector ). Let’s start with a very basic model:   Basically an entity that unidirectionally associates with a referred one. Let’s say we have these example database conventions: Identifier column are named “c”+EntityName+”Id” and are autoincrement Column description are named “txt”+EntityName+”Descr” Column of type string have to be prefixed with “txt” Column of type string have to be AnsiString ( for DDL generation of CHAR instead of NChar ) Foreign key column have to be called “c”+ForeignEntityName+”Id” So let’s see how we wrote the custom model mapper: class AutoMapper:ModelMapper { public AutoMapper() : base(new AutoModelInspector()) { //subscribe required ebvents for this simple strategy ... this.BeforeMapClass += new RootClassMappingHandler(AutoMapper_BeforeMapClass); this.BeforeMapProperty += new PropertyMappingHandler(AutoMapper_BeforeMapProperty); this.BeforeMapManyToOne += new ManyToOneMappingHandler(AutoMapper_BeforeMapManyToOne); //... //other events.... } void AutoMapper_BeforeMapManyToOne(IModelInspector modelInspector, PropertyPath member, IManyToOneMapper propertyCustomizer) { // // name the column for many to one as // "c"+foreignEntityName+"id" // var pi = member.LocalMember as PropertyInfo; if (null != pi) { propertyCustomizer.Column(k => k.Name("c"+pi.PropertyType.Name+"Id")); } } void AutoMapper_BeforeMapProperty(IModelInspector modelInspector, PropertyPath member, IPropertyMapper propertyCustomizer) { // // Treat description as a special case: "txt"+EntityName+"Descr" // but for all property of type string prefix with "txt" // if (member.LocalMember.Name == "Description") { propertyCustomizer.Column(k => { k.Name("txt" + member.GetContainerEntity(modelInspector).Name + "Descr"); k.SqlType("AnsiString"); } ); } else { var pi = member.LocalMember as PropertyInfo; if (null != pi && pi.PropertyType == typeof(string)) { propertyCustomizer.Column(k => { k.Name("txt" + member.LocalMember.Name); k.SqlType("AnsiString"); } ); } } } void AutoMapper_BeforeMapClass(IModelInspector modelInspector, Type type, IClassAttributesMapper classCustomizer) { // // Create the column name as "c"+EntityName+"Id" // classCustomizer.Id(k => { k.Generator(Generators.Native); k.Column("c" + type.Name + "Id"); }); } }   The event handlers apply the convention we said before. As we see we pass a special model inspector in the constructor, that is implemented as below: class AutoModelInspector:IModelInspector { #region IModelInspector Members public IEnumerable<string> GetPropertiesSplits(Type type) { return new string[0]; } public bool IsAny(System.Reflection.MemberInfo member) { return false; } public bool IsComponent(Type type) { return false; } public bool IsEntity(Type type) { return true; } public bool IsManyToOne(System.Reflection.MemberInfo member) { //property referring other entity is considered many-to-ones... var pi = member as PropertyInfo; if (null != pi) { return pi.PropertyType.FullName.IndexOf("MappingByCode") != -1; } return false; } public bool IsMemberOfComposedId(System.Reflection.MemberInfo member) { return false; } public bool IsMemberOfNaturalId(System.Reflection.MemberInfo member) { return false; } public bool IsPersistentId(System.Reflection.MemberInfo member) { return member.Name == "Id"; } public bool IsPersistentProperty(System.Reflection.MemberInfo member) { return member.Name != "Id"; } public bool IsProperty(System.Reflection.MemberInfo member) { if (member.Name != "Id") // property named id have to be mapped as keys... { var pi = member as PropertyInfo; if (null != pi) { // just simple stading that if a property is an entity we have // a many-to-one relation type, so property is false if (pi.PropertyType.FullName.IndexOf("MappingByCode") == -1) return true; } } return false; } public bool IsRootEntity(Type type) { return type.BaseType == typeof(object); } public bool IsTablePerClassSplit(Type type, object splitGroupId, System.Reflection.MemberInfo member) { return false; } public bool IsVersion(System.Reflection.MemberInfo member) { return false; } #endregion }   As we say there is a bounch of IsXXXXX function, that are called for each portion of the class in order to know what to do with it. Our implementation is absolutely incomplete ( not implemented function omitted ), but it feet the simple requirement we stated. Then we can see how we actually realize the mapping: static void Main(string[] args) { AutoMapper mapper = new AutoMapper(); //this line simple rely on the fact //all and just the entities are exported... var map = mapper.CompileMappingFor(Assembly.GetExecutingAssembly().GetExportedTypes()); //dump the mapping on the console XmlSerializer ser = new XmlSerializer(map.GetType()); ser.Serialize(Console.Out, map); } Simple, isn’t ? The resulting map, as dumped on the console is:   That fulfill the actually simple requirements. So is just a matter of recognize the convention and the exceptions, and let’s go auto-mapping! [Less]
Posted over 12 years ago by gabriel.schenker
Note: This post has been cross posted from my own blog at Los Techies. I am very pleased to announce that my book NHibernate 3 Beginners Guide has finally been published. It is a wonderful feeling to finally have a book in my hands that cost me a ... [More] couple of months of intense work. But I think the result is well worth it. If you are interested in the book then there is also a free chapter available for download. I was lucky to have Fabio Maulo and José F. Romaniello as my reviewer, the former being the lead of the NHibernate project and the latter an active contributor to the the project. My goal for this book has been to provide an easy to follow introduction to NHibernate 3.x. The text covers NHibernate up to version 3.1 GA and even references some of the new features of NHibernate 3.2 GA. It was very important to me to not use a data centric approach but rather choose a model first approach. In this regard this book is NOT just an updated version of NHibernate 2 Beginners Guide but rather a complete rewrite. I also have paid attention to cover all foundational topics in a clear and concise way. In no way did I want to abandon the reader in the dust of uncertainty. Let me provide you the list of chapters found in the book with a short introduction about the respective content of each chapter. Chapter 1, First Look… explains what NHibernate is and why we would use it in an application that needs to access data in a relational database. The chapter also briefly presents what is new in NHibernate 3.x compared to the version 2.x and discusses how one can get this framework. Links to various sources providing documentation and help are presented. Chapter 2, A First Complete Sample…walks through a simple yet complete sample where the core concepts of NHibernate and its usage are introduced. Chapter 3, Creating a Model… discusses what a domain model is and what building blocks constitute such a model. In an exercise the reader creates a domain model for a simple ordering system. Chapter 4, Defining the Database Schema…explains what a database schema is and describes in details the individual parts comprising such a schema. A schema for the ordering system is created in an exercise. Chapter 5, Mapping the Model to the Database…teaches how to bridge the gap between the domain model and the database schema with the aid of some wiring. This chapter presents four distinct techniques how the model can be mapped to the underlying database or vice versa. It is also shown how we can use NHibernate to automatically create the database schema by leveraging the meta-information contained in the domain model. Chapter 6, Sessions and Transactions…teaches how to create NHibernate sessions to communicate with the database and how to use transactions to group multiple tasks into one consistent operation which succeeds or fails as a whole. Chapter 7, Testing, Profiling, Monitoring and Logging…introduces how to test and profile our system during development to make sure we deliver a reliable, robust and maintainable application. It also shows how an application can be monitored in a productive environment and how it can log any unexpected or faulty behavior. Chapter 8, Configuration… explains how we can tell NHibernate which database to use, as well as provide it the necessary credentials to get access to the stored data. In addition to that many more settings for NHibernate to tweak and optimize the database access are explained in this chapter. Chapter 9, Writing Queries… discusses the various means how we can easily and efficiently query data from the database to create meaningful reports on screen or on paper. Chapter 10, Validating the data to persist…discusses why data collected by an application needs to be correct, complete and consistent. It shows how we can instrument NHibernate to achieve this goal through various validation techniques. Chapter 11, Common Pitfalls – Things to avoid… as the last chapter of this book presents the most common errors developers can make when using NHibernate to write or read data to and from the database. Each such pitfall is discussed in details and possible solutions to overcome the problems are shown. [Less]
Posted almost 13 years ago by Jose Romaniello
I will show you in this post two tricks you can do to enhance and add value to your nhibernate logs. Format Sql This is widely know trick, you can add a configuration setting to your hibernate.cfg.xml, app.config or web.config as follow: ... [More] <property name="hibernate.format_sql" value="true" /> or you can simply do it in code: config.DataBaseIntegration(db => db.LogFormatedSql = true) with this trick you will get nicely formated sql in your logs files. Logging the session identifier All nice, we have a bunch of sql logs, but we don’t know which queries belongs to which sessions. This might be useful when you are debugging an application with multiples threads or requests. I found this trick inside NHibernate, the easy way I found so far is to add a log4net appender like this one: <appender name="NHibernateAppender" type="log4net.Appender.RollingFileAppender"> <appendToFile value="true"/> <datePattern value="yyyyMMdd"/> <file value="./logs/NHibernate.log"/> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="�te Session id: %property{sessionId} - %message%newline"/> </layout> <rollingStyle value="Date"/> </appender> See the %property{sessionId} in the conversion pattern? Well, in order to log something there you need to do two steps. Add a class like this one: public class SessionIdCapturer { public override string ToString() { return SessionIdLoggingContext.SessionId.ToString(); } } Add the following code in some place at the application initialization: ThreadContext.Properties["sessionId"] = new SessionIdCapturer(); That is all! I found this code inside a nhibernate test.. it is something not very known. After doing so, your logs will look like: 2011-05-05 18:35:59,899 Session id: 5e172068-5064-44b6-bf96-99362ca05c46 - SELECT myFoo0_.AccountId as AccountId3_0_, myFoo0_.Name as Name3_0_, myFoo0_.Version as Version3_0_ FROM MyFoo myFoo0_ WHERE myFoo0_.AccountId=@p0; @p0 = 1 [Type: Int32 (0)] Another way to have this information (and much more) is to use the nhprof tool. [Less]
Posted about 13 years ago by Jose Romaniello
I’ve created a new nuget package; “NHibernate.SetForNet4”. The package is only one file that will be inserted in your project. This class contains the implementation for the Set<T> and SortedSet<T>. After you install ... [More] NHibernate.SetForNet4; the only thing you have to do is to add the collection factory to your configuration as follows: configuration.Properties[Environment.CollectionTypeFactoryClass] = typeof(Net4CollectionTypeFactory).AssemblyQualifiedName; this is a sample mapping: <?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateSetForNet4" namespace="NHibernateSetForNet4"> <class name="Person"> <id name="Id"> <generator class="hilo"/> </id> <property name="Name" /> <property name="Age" /> <set name="Tags" access="field.camelcase"> <key column="PersonId" /> <element column="Tag" /> </set> <set name="Childs" access="field.camelcase" cascade="persist" sort="PersonByAgeComparator"> <key column="ParentId" /> <one-to-many class="Person" /> </set> </class> </hibernate-mapping> this is the class: public class Person { private readonly ISet<string> tags = new HashSet<string>(); private readonly ISet<Person> childs = new SortedSet<Person>(new PersonByAgeComparator()); public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual int Age { get; set; } public virtual ISet<string> Tags { get { return tags; } } public virtual ISet<Person> Childs { get { return childs; } } } ISet<T>, HashSet<T> and SortedSet<T> are from System.Collections.Generics (.Net 4). All these tests are green: [TestFixture] public class Fixture { private ISessionFactory sessionFactory; private int personId; [TestFixtureSetUp] public void SetUp() { var configuration = new Configuration(); configuration.Properties[Environment.CollectionTypeFactoryClass] = typeof(Net4CollectionTypeFactory).AssemblyQualifiedName; configuration.Configure(); var schemaExport = new SchemaExport(configuration); schemaExport.Execute(true, true, false); sessionFactory = configuration.BuildSessionFactory(); InitializeData(); } private void InitializeData() { using (var s = sessionFactory.OpenSession()) using (var tx = s.BeginTransaction()) { var person = new Person { Name = "Pipo" }; person.Childs.Add(new Person { Name = "Jose", Age = 1 }); person.Childs.Add(new Person { Name = "Juan", Age = 5 }); person.Childs.Add(new Person { Name = "Francisco", Age = 10 }); person.Tags.Add("one"); person.Tags.Add("two"); person.Tags.Add("three"); s.Persist(person); personId = person.Id; tx.Commit(); } } [Test] public void CanGetAPersonWithTags() { using(var s = sessionFactory.OpenSession()) using (s.BeginTransaction()) { var person = s.Get<Person>(personId); person.Tags.Should().Have.SameValuesAs("one", "two", "three"); } } [Test] public void SortedSetShouldWork() { using (var s = sessionFactory.OpenSession()) using (s.BeginTransaction()) { var person = s.Get<Person>(personId); person.Childs .Select(p => p.Age).ToArray() .Should().Have.SameSequenceAs(10, 5, 1); } } [Test] public void LazyLoadShouldWork() { using (var s = sessionFactory.OpenSession()) using (s.BeginTransaction()) { var person = s.Get<Person>(personId); s.Statistics.EntityCount.Should().Be.EqualTo(1); person.Childs.ToArray(); s.Statistics.EntityCount.Should().Be.EqualTo(4); } } } The implementation of the proxy collections is a copy from the Iesi version. Let me know if you find some bug. The raw code is here. Note: you still need Iesi.Collections.dll somewhere because nhibernate internals are tied to these collections, but you don’t longer need to reference it in your domain. [Less]
Posted about 13 years ago by Jose Romaniello
In this post I’ll describe a mechanism to manage nhibernate session following the widely known patter “session-per-request”. Introduction The session-per-request pattern is very well defined and widely used; as follows A single Session and a ... [More] single database transaction implement the processing of a particular request event (for example, a Http request in a web application). What do we have currently? The first thing you will notice when talking about nhibernate session management is a little interface inside NHibernate; public interface ICurrentSessionContext { ISession CurrentSession(); } The only purpose of the implementors is to store and retrieve the current session from somewhere. This class is used by the SessionFactory of nhibernate when calling the method GetCurrentSession(). There are lot of implementations of ICurrentSessionContext but for web the two more important are: WebSessionContext inside NHibernate (namespace NHibernate.Context) WebSessionContext inside uNhAddIns.Web (namespace Session.Easier) They are pretty similar but the one inside uNhAddins supports multi-session-factory scenarios. Where do we init & store the session? We have an httpmodule in uNhAddins which add handler for the BeginRequest as follows: The problem Although the afore mentioned handler does not open a session and a transaction for images or JavaScript files there might be some request to pages that will not talk with the persistence and we don’t want a OpenSession/BeginTransaction there. Ayende already talked about this in his blog. But the problem is that he only wrote about the Session which is really light to instantiate. The problem is how do we handle the scope of the transaction which is not so light? Alternative approaches There are currently three approaches for this problem: Use BeginRequest/EndRequest to open/close the session. Handle the transaction with AOP – attributes. I am not sure but I think this is the case for the AutoTransaction facility of castle. To use Asp.Net MVC ActionFilters to Open/Close the session and the transaction. There is a third which is an antipattern; using implicit transactions for most of the cases and explicit for some others. The main problem with these approaches is that you need to explicitly put something to say that some piece of code will use a session/transaction. Even if you do it with AOP! My new solution My new solution is to store a Lazy<ISession> per request instead an ISession and initialize in the first usage and finalize in the EndRequest – only if it was used. The implementation I’ll show also support multi-session factories. The ICurrentSessionContext looks as follows: public class LazySessionContext : ICurrentSessionContext { private readonly ISessionFactoryImplementor factory; private const string CurrentSessionContextKey = "NHibernateCurrentSession"; public LazySessionContext(ISessionFactoryImplementor factory) { this.factory = factory; } /// <summary> /// Retrieve the current session for the session factory. /// </summary> /// <returns></returns> public ISession CurrentSession() { Lazy<ISession> initializer; var currentSessionFactoryMap = GetCurrentFactoryMap(); if(currentSessionFactoryMap == null || !currentSessionFactoryMap.TryGetValue(factory, out initializer)) { return null; } return initializer.Value; } /// <summary> /// Bind a new sessionInitializer to the context of the sessionFactory. /// </summary> /// <param name="sessionInitializer"></param> /// <param name="sessionFactory"></param> public static void Bind(Lazy<ISession> sessionInitializer, ISessionFactory sessionFactory) { var map = GetCurrentFactoryMap(); map[sessionFactory] = sessionInitializer; } /// <summary> /// Unbind the current session of the session factory. /// </summary> /// <param name="sessionFactory"></param> /// <returns></returns> public static ISession UnBind(ISessionFactory sessionFactory) { var map = GetCurrentFactoryMap(); var sessionInitializer = map[sessionFactory]; map[sessionFactory] = null; if(sessionInitializer == null || !sessionInitializer.IsValueCreated) return null; return sessionInitializer.Value; } /// <summary> /// Provides the CurrentMap of SessionFactories. /// If there is no map create/store and return a new one. /// </summary> /// <returns></returns> private static IDictionary<ISessionFactory, Lazy<ISession>> GetCurrentFactoryMap() { var currentFactoryMap = (IDictionary<ISessionFactory,Lazy<ISession>>) HttpContext.Current.Items[CurrentSessionContextKey]; if(currentFactoryMap == null) { currentFactoryMap = new Dictionary<ISessionFactory, Lazy<ISession>>(); HttpContext.Current.Items[CurrentSessionContextKey] = currentFactoryMap; } return currentFactoryMap; } } The new HttpModule is: public class NHibernateSessionModule : IHttpModule { private HttpApplication app; private ISessionFactoryProvider sfp; public void Init(HttpApplication context) { app = context; sfp = (ISessionFactoryProvider) context.Application[SessionFactoryProvider.Key]; context.BeginRequest += ContextBeginRequest; context.EndRequest += ContextEndRequest; } private void ContextBeginRequest(object sender, EventArgs e) { foreach (var sf in sfp.GetSessionFactories()) { var localFactory = sf; LazySessionContext.Bind( new Lazy<ISession>(() => BeginSession(localFactory)), sf); } } private static ISession BeginSession(ISessionFactory sf) { var session = sf.OpenSession(); session.BeginTransaction(); return session; } private void ContextEndRequest(object sender, EventArgs e) { foreach (var sf in sfp.GetSessionFactories()) { var session = LazySessionContext.UnBind(sf); if (session == null) continue; EndSession(session); } } private static void EndSession(ISession session) { if(session.Transaction != null && session.Transaction.IsActive) { session.Transaction.Commit(); } session.Dispose(); } public void Dispose() { app.BeginRequest -= ContextBeginRequest; app.EndRequest -= ContextEndRequest; } } You can see here how we bind to the Lazy to the current context and the initializer. The BeginSession method initializes a session and a transaction. The UnBind method returns a session only if the Lazy was initialized. If it returns something we properly commit the transaction and dispose the session. The ISessionFactoryProvider is: public interface ISessionFactoryProvider { IEnumerable<ISessionFactory> GetSessionFactories(); } and the SessionFactoryProvider is just an store for the constant: public class SessionFactoryProvider { public const string Key = "NHibernateSessionFactoryProvider"; } I didn't write an implementation for ISessionFactoryProvider because I’m using castle typed factories. The IWindsorInstaller for castle looks as follows: public class NHibernateInstaller : IWindsorInstaller { #region IWindsorInstaller Members public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register(Component.For<ISessionFactory>() .UsingFactoryMethod(k => BuildSessionFactory())); container.Register(Component.For<NHibernateSessionModule>()); container.Register(Component.For<ISessionFactoryProvider>().AsFactory()); container.Register(Component.For<IEnumerable<ISessionFactory>>() .UsingFactoryMethod(k => k.ResolveAll<ISessionFactory>())); HttpContext.Current.Application[SessionFactoryProvider.Key] = container.Resolve<ISessionFactoryProvider>(); } #endregion public ISessionFactory BuildSessionFactory() { var config = new Configuration().Configure(); //your code here :) return config.BuildSessionFactory(); } } How to use the ISession from my code? The same way I do since long time ago; public class Dao<T> : IDao<T> { private readonly ISessionFactory sessionFactory; public Dao(ISessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public void Save(T transient) { sessionFactory.GetCurrentSession().Save(transient); } //Other methods Finally I hope you find this useful. You can copy&paste all the code from this gist. [Less]
Posted about 13 years ago by Kathleen Erickson
If you are using NHibernate and suddenly find yourself needing to integrate with a Flex client, this article written by Joseph Magly will be helpful. http://www.adobe.com/devnet/flex/articles/flex-nhibernate.html