What is fluent hibernate? - nhibernate

What is fuentHibernate? Why is it used? What is the difference between Hibernate and Fluent Hibernate?

Fluent NHibernate offers an alternative to NHibernate's standard XML mapping files. Rather than writing XML documents (.hbm.xml files), Fluent NHibernate lets you write mappings in strongly typed C# code. This allows for easy refactoring, improved readability and more concise code.
Traditional HBM XML mapping
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="QuickStart" assembly="QuickStart">
<class name="Cat" table="Cat">
<id name="Id">
<generator class="identity" />
</id>
<property name="Name">
<column name="Name" length="16" not-null="true" />
</property>
<property name="Sex" />
<many-to-one name="Mate" />
<bag name="Kittens">
<key column="mother_id" />
<one-to-many class="Cat" />
</bag>
</class>
</hibernate-mapping>
Fluent NHibernate equivalent
public class CatMap : ClassMap<Cat>
{
public CatMap()
{
Id(x => x.Id);
Map(x => x.Name)
.Length(16)
.Not.Nullable();
Map(x => x.Sex);
References(x => x.Mate);
HasMany(x => x.Kittens);
}
}

Related

NHibernate mapping by code Map collection

I'm moving from xml mapping to a code based mapping. There is a problem I'm experiencing with NHibernate Map collection.
Below is the xml mapping which perfectly works (it is a bit simplified, there is actually more properties and collections):
<class name="Company" where="IsDeleted=0" lazy="false">
<id name="Id">
<generator class="guid"></generator>
</id>
<map name="Contacts" lazy="true" cascade="all" where="IsDeleted=0">
<key column="CompanyId"></key>
<index column="Id" type="guid"></index>
<one-to-many class="CompanyContact"/>
</map>
</class>
The alternate code mapping I came up with is next:
public CompanyMap()
{
Id(x => x.Id, mapper => mapper.Generator(Generators.Guid));
Map(x => x.Contacts,
m =>
{
m.Where(FILTER);
m.Cascade(Cascade.All);
m.Lazy(CollectionLazy.Lazy);
m.Key(c => c.Column("CompanyId"));
}, k =>
{
k.Element(e =>
{
e.Column("Id");
});
k.OneToMany(e => e.Class(typeof(CompanyContact)));
});
}
The above generates next hbml for map:
<map name="Contacts" lazy="true" cascade="all" where="IsDeleted=0">
<key column="CompanyId" />
<map-key type="Guid" />
<one-to-many class="CompanyContact" />
</map>
I'm obviously lacking index column here. Therefore when generating SQL nhibernate will use the DefaultIndexColumnName which is idx.
So the question is how would I set the index for map?
Update:
According to hibernate documentation I should be using map-key.
So to rephrase the question, how would I set the column property of map-key?
This is not yet implemented for NHibernate version 3.3.1.
Created an issue in Jira for that.

Fluent Nhibernate fails during insert

I have problem using Fluent Nhibernate, I have following model. When I try to save Hotel with has new Geography I getting foreign key exception, looks like Nhibenate fails to save data in correct order, is it something I can correct via Fluent Nhibernate ?
public class Geography {
public virtual int CityID { get; set; }
public virtual string CountryCode { get; set; }
}
public class Hotel
{
public virtual int HotelID { get; set; }
public virtual Geography City { get; set; }
}
Mapping
public class HotelMap : ClassMap<Hotel>
{
public HotelMap()
{
Id(x => x.HotelID)
.GeneratedBy
.Identity();
References(x => x.City, "CityId")
.Cascade.All();
}
}
public class GeographyMap : ClassMap<Geography>
{
public GeographyMap()
{
Id(x => x.CityID);
Map(x => x.CountryCode);
HasMany(a => a.Hotels)
.Cascade.All();
}
}
Added generated mappings
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="Hotel" table="`Hotel`">
<id name="HotelID" type="System.Int32">
<column name="HotelID" />
<generator class="assigned" />
</id>
<many-to-one cascade="all" class="Geography" foreign-key="HotelGeography" name="City">
<column name="CityId" />
</many-to-one>
</class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="Geography" table="`Geography`">
<id name="CityID" type="System.Int32">
<column name="CityID" />
<generator class="assigned" />
</id>
<bag cascade="all" inverse="true" name="Hotels" mutable="true">
<key>
<column name="HotelID" />
</key>
<one-to-many class="Hotel" />
</bag>
<property name="CountryCode" type="System.String">
<column name="CountryCode" />
</property>
</class>
</hibernate-mapping>
Try to specify identity generator for Geography class. If you want to have a database-generated unique identifier (like identity), you can accomplish that by adding .GeneratedBy.Native() to your Id(...) in GeographyMap class.
Add .Inverse() to the collection mapping.
For more details, have a look at http://nhibernate.info/doc/nhibernate-reference/collections.html#collections-onetomany and http://nhibernate.info/doc/nhibernate-reference/collections.html#collections-bidirectional

How to represent next nhibernate xml in fluent-nhibernate?

How to represent next nhibernate xml in fluent-nhibernate?
<set name="Items" lazy="true" table="CATEGORY_ITEMS">
<key column="CATEGORY_ID"/>
<composite-element class="CategorizedItem">
<parent name="Category"/>
<many-to-one name="Item"
class="Item"
column="ITEM_ID"
not-null="true"/>
<property name="Username" column="USERNAME" not-null="true"/>
<property name="DateAdded" column="DATE_ADDED" not-null="true"/>
</composite-element>
</set>
HasMany(x => x.Items)
.Table("CATEGORY_ITEMS")
.Component(com =>
{
com.ParentReference(x => x.Category);
com.References(x => x.Item)
.Not.Nullable();
com.Map(x => x.Username)
.Not.Nullable();
com.Map(x => x.DateAdded)
.Not.Nullable();
});
I encourage you to look into conventions for specifying the repetitious parts of your mappings, like the uppercase column and table names.

need help to convert this mapping file from NHibernate to Fluent NHibernate

i want to convert this mapping file from NHibernate to Fluent NHibernate
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="CustomCollectionsBasic.Core.Category, CustomCollectionsBasic.Core" table="Categories">
<id name="ID" column="CategoryID" unsaved-value="0">
<generator class="identity" />
</id>
<property name="Name" column="CategoryName" />
<bag name="ProductsInCategory" table="Products" cascade="all" inverse="true"
collection-type="CustomCollectionsBasic.Data.Collections.PersistentProductsType, CustomCollectionsBasic.Data">
<key column="CategoryID" />
<one-to-many class="CustomCollectionsBasic.Core.Product,ustomCollectionsBasic.Core" />
</bag>
</class>
</hibernate-mapping>
I try to convert it by NHibernateHbmToFluent and the result is
public class CategoryMap: ClassMap<CustomCollectionsBasic.Core.Category>
{
public CategoryMap()
{
Table("Categories");
Id(x => x.ID)
.GeneratedBy.
.UnsavedValue(0);
Map(x => x.Name, "CategoryName");
HasMany<CustomCollectionsBasic.Core.Product>(x => x.ProductsInCategory)
.AsBag()
.KeyColumn("CategoryID")
.Table("Products")
.Inverse()
.Cascade;
}
}
but it not working.
Any ideas on how to map this?
Thanks in advance.
Id(x => x.ID)
.GeneratedBy
.Identity()
.UnsavedValue(0);
I think the other stuff is OK

Fluent NHibernate IDictionary with composite element mapping

i have these 2 classes:
public class Category
{
IDictionary<string, CategoryResorce> _resources;
}
public class CategoryResource
{
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}
and this is xml mapping
<class name="Category" table="Categories">
<id name="ID">
<generator class="identity"/>
</id>
<map name="Resources" table="CategoriesResources" lazy="false">
<key column="EntityID" />
<index column="LangCode" type="string"/>
<composite-element class="Aca3.Models.Resources.CategoryResource">
<property name="Name" column="Name" />
<property name="Description" column="Description"/>
</composite-element>
</map>
</class>
and i'd like to write it with Fluent.
I found something similar and i was trying with this code:
HasMany(x => x.Resources)
.AsMap<string>("LangCode")
.AsIndexedCollection<string>("LangCode", c => c.GetIndexMapping())
.Cascade.All()
.KeyColumn("EntityID");
but i dont know how to map the CategoryResource entity as a composite element inside the Category element.
Any advice ?
thanks
I think the mapping you're looking for is something like this:
HasMany<CategoryResource>(x => x._resources)
.AsMap<string>("LangCode")
.KeyColumn("EntityID")
.Table("CategoryResources")
.Component(x =>
{
x.Map(c => c.Name);
x.Map(c => c.Description);
})
.Cascade.All();