Breeze provides a server-side assembly that supports using NHibernate with WebAPI. Breeze.WebApi.NH provides features similar to those offered by the Breeze WebAPI Entity Framework provider, and makes it easier to develop a Breeze client application by taking care of some of the server-side plumbing.
Our first NHibernate sample is available now. Please have a look and kick the wheels.
Metadata
Metadata generation from the NHibernate model mappings (whether XML files, Fluent, or mapping-by-code).
SaveChanges
SaveChanges
implementation to persist the entity changes from Breeze through the NHibernate model
BeforeSaveEntities
BeforeSaveEntities
interception point for business logic to be applied after the entites have been materialized from the HTTP request, but before they are saved to the database. This is a good place for server-side validation.
AfterSaveEntities
AfterSaveEntities
interception point for business logic to be applied after the entities have been saved, but before they have been composed in the HTTP response
OData filtering parameters
Support (via NHibernate’s LINQ provider) for OData filtering parameters in the HTTP request: $filter, $orderby, $select, $skip, $top
OData $expand
Support (via HTTP Filter, NHQueryableInclude
, and NHibernate lazy loading) for OData $expand
The following instructions assume you’re using Visual Studio 2012. Please look at the NorthBreeze sample application, where the following steps have already been performed:
Create a new project. Choose “ASP.NET MVC 4 Web Application” and the “Empty” template.
Add another project to your solution for your domain model and NHibernate mappings, and add a reference from your web project. (See the Limitations section for more about mappings)
In your web project’s web.config file, add your NHibernate configuration section and connectionStrings. You can use another way to configure NHibernate if you choose.
Add a class to configure your NHibernate model and build the SessionFactory. Here’s a simple static example:
public static class NHConfig
{
private static Configuration _configuration;
private static ISessionFactory _sessionFactory;
static NHConfig()
{
var modelAssembly = typeof(Customer).Assembly;
_configuration = new Configuration();
_configuration.Configure(); //configure from the web.config
_configuration.AddAssembly(modelAssembly); // mapping is in this assembly
_sessionFactory = _configuration.BuildSessionFactory();
}
public static Configuration Configuration
{
get { return _configuration; }
}
public static ISession OpenSession()
{
return _sessionFactory.OpenSession();
}
}
Add a class that extends Breeze.WebApi.NH.NHContext
and provides IQueryables for each of your model classes that will need to be queried through the WebAPI. It will need the Configuration
and Session
(from the NHConfig class defined above) in its constructor.
The NHContext
base class defines a GetQuery<> method that returns an NHQueryableInclude<>
for a model class. NHQueryableInclude
extends NHQueryable
to add an Include
clause that can emulate EntityFramework’s. Here’s an example for the Northwind model:
public class NorthwindContext : NHContext
{
public NorthwindContext() : base(NHConfig.OpenSession(), NHConfig.Configuration) { }
public NhQueryableInclude<Customer> Customers
{
get { return GetQuery<Customer>(); }
}
public NhQueryableInclude<Order> Orders
{
get { return GetQuery<Order>(); }
}
// ... more methods for other entities ...
}
Write your WebAPI controller class. It uses your derived NHContext class (described above) to implement the SaveChanges and Metadata methods, as well as a method that exposes each of your entities for querying. The [BreezeNHController] attribute adds a filter to each of the query methods, applyingOData parameters to the query before execution.
[BreezeNHController]
public class NorthBreezeController : ApiController
{
private NorthwindContext northwind;
protected override void Initialize(System.Web.Http.Controllers.HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
northwind = new NorthwindContext();
}
[HttpGet]
public String Metadata()
{
return northwind.Metadata();
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return northwind.SaveChanges(saveBundle);
}
[HttpGet]
public IQueryable<Customer> Customers()
{
var custs = northwind.Customers;
return custs;
}
[HttpGet]
public IQueryable<Order> Orders()
{
var orders = northwind.Orders;
return orders;
}
//... Additional methods for other entities
}
Unlike NHibernate itself, Breeze requires foreign keys that are mapped to object properties so Breeze can maintain the relationships on the client side. Here’s an example, mapping a relationship from Order to Customer:
<many-to-one name="Customer" column="`CustomerID`" class="Customer" />
<property name="CustomerID" type="System.Guid" insert="false" update="false" /> The "Customer" property is mapped normally, while the "CustomerID" property is mapped with `insert="false"` and `update="false"`. This way, the CustomerID is exposed to Breeze, but NHibernate will perform inserts and updates using the ID of the Customer object itself.
We intend to fix this in the future by auto-generating the foreign key properties on the client (using a custom JsonResultsAdapter), and adding them to the server-generated metadata.
NHibernate supports many querying methods. You may use any of them with Breeze, but we only have examples with NHQueryable at the moment.