NHibernate mapping by code equivalent for <database-object> - nhibernate-mapping

I have an NHibernate mapping that makes use of a <database-object> element that makes use of a definition class. The mapping looks a bit like this:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Foo" assembly="Foo">
<database-object>
<definition class="Foo.AuxilliaryData,Foo"/>
</database-object>
</hibernate-mapping>
This works fine, but I would like to use mapping by code as per NHibernate >=3.2. Is there a way to do this?
(Out of interest, my reason for wanting to convert this is so that R# "Find usages" will work for the AuxilliaryData class. At the moment R# (and any other code inspection tool) thinks that this class is unused).

just add it when generating the Configuration object
config.AddAuxiliaryDatabaseObject(new Foo.AuxilliaryData());

Related

Nhibernate Stored Procedure Mapping in xml file clarification

Can anyone tell where to map Stored-Procedures exactly in Nhibernate.
In class hbm.xml file or newly declared file(hbm.xml) especially for Stored Procedures???
can u tell with reason??
I create a single XML file that contains ALL stored procedure calls, e.g.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<sql-query name="SummaryReport">
exec getSummaryReport :productId
</sql-query>
<sql-query name="FullReport">
exec getFullReport :productId
</sql-query>
</hibernate-mapping>
and mark this as an embedded resource. I can then call me SP like this:-
var results = Session
.GetNamedQuery("SummaryReport")
.SetInt32("productId", productId);
.SetResultTransformer(
new AliasToBeanResultTransformer(typeof(SummaryReport)));
return results.List<SummaryReport>();
This works fine for me but there really isn't a recommended way, its always down to what you feel is right for you.

define NHibernate mappings in different assembly than the domain objects

I have an assembly Foo.Bar that holds all my domain logic and my domain object (e.g. public class Project, public interface IProjectRepository).
I also have an assembly Foo.Bar.Data that acts as my NHinbernate data access layer wich holds the IProjectRepository NHibernate-based implementation. It references Foo.Bar and contains the mapping files such as Project.hbm.xml.
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Foo.Bar"
namespace="Foo.Bar.Domain" default-lazy="false">
<class name="Project">
<id name="Id" column="ID" />
<property name="Customer" column="CUSTOMER" />
</class>
</hibernate-mapping>
Unfortunately with this setup I get the following exception:
NHibernate.MappingException : No persister for: Foo.Bar.Domain.Project
And the NHibernate log says:
WARN NHibernate.Cfg.Configuration (null) - No mapped documents found in assembly: Foo.Bar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Howver if I add the mapping file to the Foo.Bar assmbly everything works fine. But I really do not want any data access or NHinbernate implementation details into my domain assembly. This tends to be best practise, right? Is this kind of setup not a good way to go?
How can I make NHibernate find the mapping files in the Foo.Bar.Data* assembly?
Turns out that all I have to do is add
<mapping assembly="Foo.Bar.Data"/>
to my hibnerate configuration within the <session-factory> element.

property formula not returning the result

I have a table Submission, which has a many to one mapping to a SubmissionType, which has a one to many mapping to SubmissionTypeYear table. Even though this is a one-to-many mapping, there will always be just one SubmissionTypeYear for a SubmissionType. (Don't ask me why the database was designed like this. I wasn't involved and I just have to make it work.)
Therefore, a submission will have a SubmissionType will have a SubmissionTypeYear.
My problem is that in my Submission.hbm.xml, I want a calculated property, which gets me a column value from SubmissionTypeYear. But I don't know what's wrong, it comes back with a zero, when I know that there is a value in the table.
This is my code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Business.Domain" assembly="Business.Domain">
<class name="Business.Domain.Submission, Business.Domain" table="dbo.Submission" lazy="true" optimistic-lock="version" >
<id name="Id" column="SubmissionId">
<generator class="identity"/>
</id>
<discriminator column ="SubmissionTypeCode"></discriminator>
<many-to-one name="SubmissionTypeMember" insert="false" column="SubmissionTypeCode" class="RefSubmissionType" access ="field.camelcase-underscore" cascade ="none" />
<property name="Year" formula="(SELECT TOP 1 SubmissionTypeYear.Year FROM SubmissionTypeYear WHERE SubmissionTypeYear.SubmissionTypeCode = SubmissionTypeCode)" access="field.camelcase-underscore"></property>
</hibernate-mapping>
I thought that it wasn't picking up the SubmissionTypeCode correctly, so I tried with a static string as well, but doesn't seem to be working.
What am I doing wrong? Please help.
Thanks
OK, I figured it out. The problem was with the new Submission types created. As it was a new object and not yet stored in the database, it wasn't able to pick up the calculated field. It was working for all the existing objects. Fixed :)
Hope this helps someone else.

Polymorphic NHibernate mappings

I have an interface IUserLocation and a concrete type UserLocation.
When I use ICriteria, specifying the interface IUserLocation, I want NHibernate to instantiate a collection of the concrete UserLocation type.
I have created an HBM mapping file using the table per concrete type strategy (shown below). However, when I query NHibernate using ICriteria I get:
NHibernate cannot instantiate abstract class or interface MyNamespace.IUserLocation
Can anyone see why this is? (source code for the relevant bit of NHibernate here (I think))
My ICriteria:
var filter = DetachedCriteria.For<IUserLocation>()
.Add(Restrictions.Eq("UserId", userId));
return filter.GetExecutableCriteria(UoW.Session)
.List<IUserLocation>();
My mapping file:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" name="MyNamespace.IUserLocation,MyAssembly" abstract="true" table="IUserLocations">
<composite-id>
<key-property name="UserId" column="UserId" type="System.Guid"></key-property>
<key-many-to-one name="Location" column="LocationId" class="MyNamespace.ILocation,MyAssembly"></key-many-to-one>
</composite-id>
<union-subclass table="UserLocations" name="MyNamespace2.UserLocation,MyAssembly2">
<property name="IsAdmin" />
</union-subclass>
</class>
</hibernate-mapping>
From the documentation it looks like your mapping file should do it to me. I've never tried table per concrete class though. And I notice the examples in the NHibernate documentation for it don't use interfaces for the base class. Perhaps it's not supported?
I have used Table per concrete class, using implicit polymorphism before with a separate mapping for each subclass.
<class name="MyNamespace.UserLocation,MyAssembly" table="UserLocations">
...
</class>

How do I map repeating columns in NHibernate without creating duplicate properties

Given a database that has numerous repeating columns used for auditing and versioning, what is the best way to model it using NHibernate, without having to repeat each of the columns in each of the classes in the domain model?
Every table in the database repeats these same nine columns, the names and types are identical and I don't want to replicate it in the domain model.
I have read the docs and I saw the section on inheritance mapping but I couldn't see how to make it work in this scenario. This seems like a common scenario because nearly every database I've work on has had the four common audit columns (CreatedBy, CreateDate, UpdatedBy, UpdateDate) in nearly every table. This database is no different except that it introduces another five columns which are common to every table.
Use Fluent NHibernate to create your mapping files. This allows you to use inheritance with your mapping files. For example:
public class AuditableClassMap<T> : ClassMap<T> where T : IAuditable
{
public AuditableClassMap()
{
Map(x => x.CreatedBy);
Map(x => x.CreatedDate, "CreatedDt");
Map(x => x.RevisedBy);
Map(x => x.RevisedDate, "RevisedDt");
}
}
public class CompanyMap : AuditableClassMap<Company>
{
// mapping for Company
}
Using t4 code generation you should be able to write a single code generation file that outputs a single .hbm.xml file with all of your classes defined. I envision something like the following. First, create a file with the .tt extension and put in the following code:
<## template language="C#v3.5" #>
<## output extension="hbm.xml" #>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="MyNameSpace">
<#
System.Collections.Generic.Dictionary<string, string> classes = new System.Collections.Generic.Dictionary<string, string>();
classes.add("RootNameSpace.SubNameSpace.MyClass1", "Table1");
foreach(string className in classes.keys)
{
#>
<class name="<#=className#>, AssemblyName" table="<#=classes[className]#>">
<id name="ID" column="EntityID" type="Int32">
<generator class="native" />
</id>
<property name="Property1" />
<property name="Property2" />
</class>
<#
}
#>
</hibernate-mapping>
The last step would be to set the output file's Build Action to Embedded Resource and you should be good to go.
You can read more about t4 code generation here:
http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx
Instead of mapping by hand, use ConfORM.
In many cases, it will do all the work for you. When it doesn't, it's very easy to define your conventions and overrides.
This can be accomplished by using the component element in the mapping file.
The basic idea is to create a class to hold the common properties and reference it from each of the entities in your model.
Then inside your mapping file add a reference to this property like this...
<component name="RecordMetadata" class="RecordMetadata" insert="true" update="true">
<property name="UpdatedBy" />
<property name="UpdatedDate" />
<property name="CreatedBy" />
<property name="CreatedDate" />
</component>