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

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>

Related

Mapping inherited class with nhibernate hbm

I Have 2 classes of the same table.
one class, "Entity", contains properties x,y,z from table ENTITY
and the derived class, "ExtendedEntity" contains some more properties (collections - relations to other tables).
I want to map both of them but i couldn't find a way to map subclasses without using discriminator (I dont need one, sometimes i want to select the Entity object and sometimes the ExtendedEntity).
does anyone has any idea?
(I tried to map the ExtendedEntity by copying the Entity mapping and adding the new properties, but now when i want to get the Entity object it brings me ExtendedEntity).
Thanks!
Taking into account the first sentence of your question:
I Have 2 classes of the same table.
It means that there is only one table ("ENTITY"). If this is true, there do not have to be, and even should not be any inheritance, if no discriminator exists. If both entities will be related to all rows, then (instead of inheritance) we need laziness. And only one Entity profiting from the native NHibernate behavior: having lazy properties. And even more, to optimize some queries - the Projections could be used.
But again, my suggestion could be correct only if I do understand your scenario correctly: the two entities were introduced only to reduce workload; but both target all rows in one table.
The mapping for the only class
<class name="Entity" table="ENTITY" lazy="true">
<id name="ID" column="Entityd">
<generator class="native"></generator>
</id>
<!-- standard default always loaded properties -->
<property name="Code" />
<property name="Name" />
<!-- only if accessed, lazily loaded properties -->
<many-to-one lazy="proxy" name="Currency" column="CurrencyId" cascade="none" />
<property lazy="true" name="Image" column="ImageBinary" />
...
Having this mapping we can get first 5 Entities
var list = session.CreateCriteria<Entity>()
.SetMaxResults(5)
.List<Entity>();
And SQL statement generated will be:
SELECT TOP 5 this_.EntityId as EntityId3_1_
, this_.Code as Code3_1_
, this_.Name as Name3_1_
FROM ENTITY this_
And we can even reduce it with projections
var propertyList = NHibernate.Criterion.Projections.ProjectionList();
// projection properties
propertyList.Add(NHibernate.Criterion.Projections.Property("ID"));
propertyList.Add(NHibernate.Criterion.Projections.Property("Code"));
var projected = session.CreateCriteria<Entity>()
.SetMaxResults(5)
.SetProjection(propertyList)
.SetResultTransformer(new NHibernate.Transform
.AliasToBeanResultTransformer(typeof(Entity)))
.List<Entity>();
In this case is the SQL Select even smaller. If the ID and Code would be enough..
SELECT TOP 5 this_.Code as y0_
, this_.EntityId as y1_
FROM ENTITY this_
So, in case I read your question correctly, in your scenario solution would not be in inheritance but in NHibernate native laziness
NOTE: there could be ExtendedEntity derived from Entity even in this scenario. But not for inheritance via NHibernate mapping but for the Projections Transformation. Some properties from many-to-one properties could be projected this way...

Filter entities on mapping level in NHibernate

Let's say that I have and database table called People, and entity People. Let's say that I need a quick way to remove a subset of people from displaying everywhere in application. So I add IsDeleted column to People table, and set values in that column to 1.
In Entity Framework there's a mechanism that specifies that for instans of entities with value in column IsDeleted set to 1 shouldn't be fetched and mapping framework filters data automatically. Is is possible to achieve with NHibernate?
You can define where attribute in your class mapping.
where (optional) specify an arbitrary SQL WHERE condition to be used
when retrieving objects of this class
<class ... where="IsDeleted = 0">
If you are using Fluent NHibernate then just define this in mapping class:
Where("IsDeleted = 0");
NH's mapping by code should be similar to Fluent NHibernate's mapping.
You can create abstract class, e.g. PeopleBase, from which your People class will be derived and map your entity to it.
After that you can use discriminator like this (didn't check for correctness, but it should work):
<class name="YourNamespace.PeopleBase,YourNamespace" table="People">
// ...
<discriminator column="IsDeleted" type="boolean" />
// Properties...
// ...
<subclass name="YourNamespace.People, YourNamespace" discriminator-value="false">
</subclass>
</class>
In order to achieve what I wanted, I've created base class + two subclasses. This is the configuration:
subclasses with discriminator-value:
<subclass name="People" discriminator-value="null">
</subclass>
<subclass name="PeopleHistory" discriminator-value="not null">
<property name="MasterRowId" />
</subclass>
discriminator in base class:
<discriminator column="MasterRowId" />

Mapping Decorator Pattern in NHibernate

Further to this question:
Composition over Inheritance - where do extra properties go?
The accepted answer and similar ones answer this nicely. But to take this further, what if the Sales department and Production department wanted to record different information about Sickness and Holiday absences? This could be one solution:
public class Holiday : Absence
{
//Extra fields go here.
}
public class Sickness : Absence
{
//Extra fields go here.
}
public class SalesHoliday : Holiday
{
//Extra fields go here.
}
public class SalesSickness : Sickness
{
//Extra fields go here.
}
public class ProductionHoliday : Sickness
{
//Extra fields go here.
}
public class ProductionSickness : Sickness
{
//Extra fields go here.
}
clearly, this is the start of a class explosion which will only get worse, and therefore should be avoided.
One possible solution would be to use the Decorator Pattern (Gang of Four). This would be ideal but in this hypothetical example, the persistence is with NHibernate. I have looked all over the place for an example of how to map the Decorator pattern in NHibernate and not found anything. My experiments have, and one point, utilised various combinations of subclass mappings, joined-subclass mappings, union-subclass mappings, discriminators, implicit polymorphism and many-to-any mappings, but so far with no satisfactory results. Has anyone cracked this one? An Employee entity would have a collection of absences of any type so polymorphic behavior is a requirement.
In modeling this particular type of application I would try to stay away from sub-classing an absence based on department. Instead, I would try to make the absence handling system capable of supporting any department. You can devise a model that allows adding custom properties to an absence if that becomes necessary. This could be done using either a generic notes field or a dictionary. This data could then be further structured by a given context, such as Sales and Production.
One way to think of this is that an absence in the sales department is much like an absence in the production department, so the 'type' of the entity does not change. What may change is particular details about an absence, which in turn warrants the composition over inheritance approach.
I finally answered my own question. Union-subclass is the way forward, like in this pizza example:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Decorator.Domain.Entities"
assembly="Decorator.Domain">
<class name="IPizza" abstract="true">
<id name="Id" column="Id" type="guid">
<generator class="assigned"/>
</id>
<many-to-one name="Order" class="Order" column="`OrderId`" cascade="save-update" />
<union-subclass name="Pizza" table ="`Pizza`" >
<property name="Size" column="`Size`" />
<property name="Cheese" />
<property name="Tomato" />
</union-subclass>
<union-subclass name="PepperoniDecorator" table ="`PepperoniDecorator`" >
<many-to-one name="BasePizza" class="IPizza" column="`BasePizzaId`" cascade="all" />
<property name="ExtraSpicy" column="`ExtraSpicy`" />
</union-subclass>
<union-subclass name="OliveDecorator" table ="`OliveDecorator`" >
<many-to-one name="BasePizza" class="IPizza" column="`BasePizzaId`" cascade="all" />
<property name="Colour" column="`Colour`" />
</union-subclass>
</class>
</hibernate-mapping>
I go in to this in more detail on my blog:
http://lucidcoding.blogspot.co.uk/2013/07/mapping-decorator-pattern-in-nhibernate.html

How do I use structural annotations to set SQL type to Date in model first approach

Is it possible to set type to just date (NOT datetime) via entity framework designer?
I had a look around and the only answer that I've found is a post from MSDN forum from a year ago...
http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/28e45675-f64b-41f0-9f36-03b67cdf2e1b
I'm very new here and I don't really understand the instructions where they talk about structural annotations...
I can go through the generated SQL script and change each line but I rather not do that...
Structural annotation - nice. It is the first time I heard about this feature but it works. I just tried it. I will try to explain it little bit.
Structural annotations are just random xml added to EDMX file. EDMX file is in fact just XML wich has 4 parts - CSDL, MSL, SSDL and part related to positioning elements in the designer.
CSDL describes entities and associations among entities (defined in the designer)
SSDL describes tables and relations
MSL describes mapping between CSDL and SSDL
If you start with model first (you want to generate database from your model), you have only CSDL part and both SSDL and MSL will be generated by some automatic process (T4 templates executed in workflow) once SSDL is created another T4 template will generate SQL script for database creation.
Structural annotation described in linked MSDN forum's thread is a hint. You will place structural annotation into CSDL part of the EDMX (you must open EDMX as XML - click on the file in solution explorer and choose Open with). My test CSDL describes single User entity with three properties (entity is visible on screenshot later in the answer):
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm"
xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
xmlns:custom="http://tempuri.org/custom"
Namespace="Model" Alias="Self" >
<EntityContainer Name="ModelContainer" annotation:LazyLoadingEnabled="true">
<EntitySet Name="UsersSet" EntityType="Model.User" />
</EntityContainer>
<EntityType Name="User">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Type="Int32" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
<Property Type="String" Name="Login" Nullable="false" />
<Property Type="DateTime" Name="CreatedAt" Nullable="false">
<custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
</Property>
</EntityType>
</Schema>
</edmx:ConceptualModels>
I have added custom namespace definition in Schema element: xmlns:custom="http://tempuri.org/custom" and defined custom structural annotation for CreatedAt property:
<Property Type="DateTime" Name="CreatedAt" Nullable="false">
<custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
</Property>
The name of the namespace or element used for structural annotation are not important - it is absolutely up to you what names do you use. The only important thing is edmx:CopyToSSDL="true" attribute. This attribute is recognized by T4 template used for SSDL creation and it just takes this element and places it to SSDL. Generated SSDL looks like:
<Schema Namespace="Model.Store" Alias="Self"
Provider="System.Data.SqlClient" ProviderManifestToken="2008"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<EntityContainer Name="ModelStoreContainer">
<EntitySet Name="UsersSet" EntityType="Model.Store.UsersSet" store:Type="Tables" Schema="dbo" />
</EntityContainer>
<EntityType Name="UsersSet">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />
<Property Name="Login" Type="nvarchar(max)" Nullable="false" />
<Property Name="CreatedAt" Type="datetime" Nullable="false">
<custom:SqlType xmlns:custom="http://tempuri.org/custom">Date</custom:SqlType>
</Property>
</EntityType>
</Schema>
The only point was moving the structural annotation to SSDL. All annotations are accessible in metadata through some name value collection. Now you need to modify T4 template responsible for SQL script generation to recognize this annotation and use the value defined in the annotation instead of type defined in the property. You can find the template in:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt
Copy template file to new location (so that you don't modify the original one) and replace default table creation with this:
-- Creating table '<#=tableName#>'
CREATE TABLE <# if (!IsSQLCE) {#>[<#=schemaName#>].<#}#>[<#=tableName#>] (
<#
for (int p = 0; p < entitySet.ElementType.Properties.Count; p++)
{
EdmProperty prop = entitySet.ElementType.Properties[p];
#>
[<#=Id(prop.Name)#>] <#
if (prop.MetadataProperties.Contains("http://tempuri.org/custom:SqlType"))
{
MetadataProperty annotationProperty = prop.MetadataProperties["http://tempuri.org/custom:SqlType"];
XElement e = XElement.Parse(annotationProperty.Value.ToString());
string value = e.Value.Trim();
#>
<#=value#> <# } else { #> <#=prop.ToStoreType()#> <# } #> <#=WriteIdentity(prop, targetVersion)#> <#=WriteNullable(prop.Nullable)#><#=(p < entitySet.ElementType.Properties.Count - 1) ? "," : ""#>
<#
}
#>
);
GO
Now the last point is changing the template used for SQL script generation. Open EDMX file in the designer and go to model's properties (just click somewhere in the designer while you have properties window opened). Change DDL Generation Template to the template you modified.
Run Generate Database from Model and it will create SQL script containing:
-- Creating table 'UsersSet'
CREATE TABLE [dbo].[UsersSet] (
[Id] int IDENTITY(1,1) NOT NULL,
[Login] nvarchar(max) NOT NULL,
[CreatedAt] Date NOT NULL
);
GO
This is probably the most advanced and hidden feature of EDMX I have seen yet. Annotations together with custom T4 templates can get you a lot of control over both class and SQL generation. I can imagine using this to define for example database indexes or unique keys when using model first or add selectively some custom attributes to generated POCO classes.
The reason why this is so hidden is that there is no tooling support in VS out-of-the box to use this.
From NuGet look for TiraggoEdmx, it serves up all the low level information from your EDMX files in a very nice way. See http://brewdawg.github.io/Tiraggo.Edmx/

Hibernate mappings: Splitting up the file

Alright, I've got a quick question. I'm currently working with a legacy database, so I can't change around much. The database revolves around a single type, the entity. All other relevant data (except for customizable lists etc.) 'inherit' from this.
I'm mapping this with a joined subclass approach, which is working fine. The problem however, is that my mapping file is reaching hideous proportions. I would like to split up the file in multiple separate files, but I'm not sure if this is possible and how to approach this problem. I've read through the Hibernate docs on the official site, but couldn't find anything.
To clarify, mappings look like this:
<class name="..." table="...">
<id ...>
<generator class="org.hibernate.id.TableHiLoGenerator">
<param name="table">...</param>
<param name="column">...</param>
</generator>
</id>
<property name="somethingCommon" />
<joined-subclass name="class_1">
...
...
</joined-subclass>
<joined-subclass name="class_2">
...
...
</joined-subclass>
...
<joined-subclass name="class_n">
...
...
</joined-subclass>
</class>
What I would like to be able to do is put the joined-subclass bits in separate files, just like I would do in code (separate classes -> separate files). Is this possible using just mappings, or perhaps by manipulating the mappings when I load them?
(Note: tagged hibernate/nhibernate, as I don't think this is specific to either flavor)
I believe you can use "extends" eg:
<hibernate-mapping>
<joined-subclass name="DomesticCat" extends="Cat">
...
</joined-subclass>
to separate out the joined subclasses into separate files.