Getting started with NHibernate - nhibernate

I am trying to develop my Hello World program in NHibernate.
My codes are as follows:
MyClass.cs
----------
using System.Collections.Generic;
using System.Text;
using System;
using NHibernate.Collection;
using NHibernate.Mapping;
using Iesi.Collections;
namespace NHibernate__MyClass
{
public class MyClass
{
int id;
string name;
int _value;
public MyClass()
{
id = 0;
name = "";
_value = 0;
}
public virtual int Id
{
get { return id; }
set { id= value; }
}
public virtual string Name
{
get { return name; }
set { name= value; }
}
public virtual int Value
{
get { return _value; }
set { _value= value; }
}
}
}
MyClass.hbm.xml
---------------
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NHibernate__MyClass" assembly="NHibernate__MyClass">
<class name="MyClass" table="MyClass">
<id name="Id">
<column name="ID" sql-type="int" not-null="true"/>
<generator class="native" />
</id>
<property name="Name">
<column name="Name" not-null="true" />
</property>
<property name="Value">
<column name="Value" not-null="true" />
</property>
</class>
</hibernate-mapping>
Program.cs
----------
using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
namespace NHibernate__MyClass
{
class Program
{
static void Main(string[] args)
{
MyClass myClass = new MyClass();
myClass.Id = 1;
myClass.Name = "Hello World!";
myClass.Value = 100;
ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
ISession session = sessionFactory.OpenSession();
session.BeginTransaction();
session.Save(myClass);
session.Transaction.Commit();
Console.ReadLine();
}
}
}
App.config
----------
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"
/>
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.connection_string">Data Source=.\SQLEXPRESS;Initial Catalog=NHibernate;Integrated Security=True</property>
<mapping assembly="NHibernate__MyClass" />
</session-factory>
</hibernate-configuration>
</configuration>
SQL Table
---------
CREATE TABLE [dbo].[MyClass](
[ID] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
[value] [int] NOT NULL
) ON [PRIMARY]
But this program is generating an Exception:
Exception message : {"could not insert: [NHibernate__MyClass.MyClass][SQL: INSERT INTO MyClass (Name, Value) VALUES (?, ?); select SCOPE_IDENTITY()]"}
Inner Exception Message : {"Cannot insert the value NULL into column 'ID', table 'NHibernate.dbo.MyClass'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."}
What can be the problem?
NHibernate DLL version = 2.0.0.2002

Because of this tag in your mapping file
<generator class="native" />
In SQL you need to set the ID field in that table to an identity.
You can alternatively have nHibernate generate identity fields.

Related

NHibernate issue : persistent class not known

I have two tables Person and PassportInfo with a structure as given below:
Table Person
(
PersonID uniqueidentifier not null, (PK)
Name varchar(100) not null,
Email varchar(100) not null
)
Table PassportInfo
(
ID int identity(1,1) not null Primary Key,
personID uniqueidentifier null, (FK to PersonID in Person table)
PassportNumber varchar(100) not null
)
Also this is the mapping for Person
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Project" namespace="Project">
<class name="classperson" table="Person" >
<id name="ID" type="System.Guid" column="personID">
<generator class="Guid"/>
</id>
<property name="Name" column="Name" type="System.String" length="100" not-null="true" />
<property name="Email" column="Email" type="System.String" length="100" not-null="true" />
<one-to-one name="classpassportinfo" class="classpassportinfo" constrained="true" />
</class>
</hibernate-mapping>
This is the mapping for PassportInfo
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Project" namespace="Project">
<class name="classpassportinfo" table="PassportInfo" >
<id name="ID" type="System.Int32" column="ID">
<generator class="identity"/>
</id>
<property name="PassportNumber" column="PassportNumber" type="System.String" length="100" not-null="true" />
<one-to-one name="classperson" class="classperson" />
</class>
</hibernate-mapping>
This is the Object Class for Person
namespace Project
{
[Serializable]
public class classperson : Base<System.Guid>
{
private System.String _Name;
private System.String _Email;
private classpassportinfo _classpassportinfo;
public classperson()
{
}
public classperson(System.Guid id)
{
base.ID = id;
}
public virtual System.String Name {
get { return _Name; }
set { _Name = value;}
}
public virtual System.String Email {
get { return _Email; }
set { _Email = value;}
}
public virtual classpassportinfo classpassportinfo {
get { return _classpassportinfo; }
set { _classpassportinfo = value;}
}
}
}
Finally this is the object class for PassportInfo
namespace Project
{
[Serializable]
public class classpassportinfo :Base<Systme.Int32>
{
private System.String _PassportNumber;
private classpassportinfo _classpassportinfo;
public classpassportinfo()
{
}
public classpassportinfo(System.Int32 id)
{
base.ID = id;
}
public virtual System.String PassportNumber {
get { return _PassportNumber; }
set { _PassportNumber = value;}
}
public virtual classperson classperson {
get { return _classperson; }
set { _classperson = value;}
}
}
}
When I execute above code, i am getting and error saying persistent class not known: Project.classpassportinfo. I am new to nhibernate. Any help in this appreciated.
To elaborate and clarify #Fran's comment for anyone else struggling with this problem...
For me, in Visual Studio this issue was resolved by:
Open the solution explorer (Project structure navigator)
Locate the mapping file passportinfo.hbm.xml
Right click and choose properties
Under the advanced tab, make sure "Build Action" is set to "Embedded Resource"
The issue should be resolved now. Good luck

NHibernate Object reference not set to an instance of an object

This is my first time using NHibernate and i am trying to create an application using MVC 4, here is my configuration file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory >
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">Data Source=.\SQLEXPRESS;Initial Catalog=loc;Persist Security Info=True;Trusted_Connection=Yes;Pooling=yes;connection lifetime=300;User Id=sa;Password=###</property>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
<property name="show_sql">false</property>
and the mapping file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="HelloWorldHib"
namespace="HelloWorldHib.Mappings">
<class name="Product" table="Products">
<id name="Id" column="Id">
<generator class="native"></generator>
</id>
<property name="Name"></property>
<property name="Category"></property>
<property name="IsDis"></property>
</class>
</hibernate-mapping>
And the helper:
public class NHibernateHelper
{
private static ISessionFactory _sessionFactory;
private static Configuration cfg;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
{
cfg.Configure(HttpContext.Current.Server.MapPath("~/hibernate.cfg.xml"));
cfg.AddDirectory(new System.IO.DirectoryInfo(HttpContext.Current.Server.MapPath(#"~/Mappings")));
cfg.AddAssembly(typeof(Product).Assembly);
_sessionFactory = cfg.BuildSessionFactory();
if (_sessionFactory == null)
throw new InvalidOperationException("session factory could not be built");
}
return _sessionFactory;
}
}
public static ISession OpenSession()
{
ISession session;
session = _sessionFactory.OpenSession();
if (session == null)
throw new InvalidOperationException("session could not be opend");
return session;
}
}
When i run my app i get Object reference not set to an instance of an object on this line session = _sessionFactory.OpenSession()
The table exist in the database, what is the problem?
Thanks
Means that the variable _sessionFactory is null. You should use the property SessionFactory instead which will also initialize the _sessionFactory variable.
session = SessionFactory.OpenSession();

Data is not really storing database in nhibernate

I am writing a simple program using nhibernate
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using System.Data.SqlServerCe;
using NHibernate.ByteCode.LinFu;
namespace FirstSolution
{
class Program
{
static void Main(string[] args)
{
Product p = new Product();
p.id = "padu";
p.name = "Sayan";
p.category = "Bogus";
Configuration cfg = new Configuration();
cfg.AddXmlFile("C:/Users/win7/Documents/Visual Studio 2008/Projects/FirstSolution/FirstSolution/Product.hbm.xml");
try
{
using (ISessionFactory factory = cfg.BuildSessionFactory())
{
using (ISession session = factory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
// Tell NHibernate that this object should be saved
session.Save(p);
// commit all of the changes to the DB and close the ISession
session.Flush();
transaction.Commit();
session.Close();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
string s;
s = Console.ReadLine();
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
</configSections>
<connectionStrings>
<add name="FirstSolution.Properties.Settings.Database1ConnectionString"
connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory| \Database1.mdf;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="dialect">NHibernate.Dialect.MsSqlCeDialect</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="proxyfactory.factory_class">
NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu
</property>
<property name="connection.connection_string">Data Source=.\SQLEXPRESS; AttachDBFilename=|DataDirectory|Database1.mdf;Integrated Security=true;User Instance=true;</property>
<property name="show_sql">true</property>
<mapping assembly="FirstSolution"/>
</session-factory>
</hibernate-configuration>
</configuration>
Product.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="FirstSolution" assembly="FirstSolution">
<class name="Product" table="UserTable" lazy="false">
<id name="id" column="id" type="String" length="10">
<generator class="assigned"/>
</id>
<property name="name" column="name" type="String" length="10"/>
<property name="category" column="category" type="String" length="10"/>
</class>
</hibernate-mapping>
Product.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FirstSolution
{
public class Product
{
public String id { get; set; }
public String name { get; set; }
public String category { get; set; }
}
}
Program is running without any exception. Generated sql is showing on console. But no data is saved in UserTable of Database1.mdf
Database1.mdf is being copied to the /bin/Debug folder when the application is built and the data is saved there.
Hmm. I'm surprised that you don't get exceptions. The Product class must have virtual properties, otherwise it won't work.
Also, I see you're using the MsSqlCeDialect. I haven't used SqlExpress but SqlExpress != SqlCe. Trying using MsSql2005Dialect or MsSql2005Dialect.

Nhibernate one-to-one mapping

Hello guys I've tried searching for a solution to this problem for a period of time. Couldn't find it.
I have two classes which I will simplify. My problem is that i want a unidirectional one-to-one mapping between Player and Clan. Now I saw examples which have foreign key in ther id. But I don't understand it. This mapping is not producing a column in my Clans table for ClanLeader... Am i missing something? Thank you all for help.
public class Clan{
private Int32 id;
public virtual Int32 Id
{
get { return id; }
set { id = value; }
}
private string name;
public virtual string Name
{
get { return name; }
set { name = value; }
}
private Player clanLeader;
public virtual Player ClanLeader
{
get { return clanLeader; }
set { clanLeader = value; }
}
}
Then we have mapping for Clan:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateSQLite"
namespace="NHibernateSQLite" >
<class name="GamingOrganizerDomainModel.Clan, GamingOrganizerDomainModel" table="Clans" lazy="false">
<id name="id" access="field" column="Clan_ID" type="Int32">
<generator class="native"></generator>
</id>
<property name="Name" column="Clan_Name" unique-key="ClanNameConstraint" type="String"/>
<one-to-one name="ClanLeader" class="GamingOrganizerDomainModel.Player, GamingOrganizerDomainModel" />
</class>
</hibernate-mapping>
Next is the class Player:
public class Player{
private Int32 id;
public virtual Int32 Id
{
get { return id; }
set { id = value; }
}
private string nickname;
public virtual string Nickname
{
get { return name; }
set { name = value; }
}
}
And mapping for Player:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateSQLite"
namespace="NHibernateSQLite" >
<class name="GamingOrganizerDomainModel.Player, GamingOrganizerDomainModel" table="Players" lazy="false">
<id name="id" column="Player_ID" access="field" type="Int32">
<generator class="native" />
</id>
<property name="nickname" access="field" column="Nickname"/>
</class>
</hibernate-mapping>
Unidirectional one to one relation should be mapped as "many-to-one" element. "one-to-one" is used for bidirectional one to one. See this post for more details. Howerver there are ConfORM mappings as well the article is crystal clear.
You need make only one change in your Clan mapping:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="GamingOrganizerDomainModel"
namespace="GamingOrganizerDomainModel" >
<class name="Clan" table="Clans" lazy="false">
<id name="id" access="field" column="Clan_ID" type="Int32">
<generator class="native"></generator>
</id>
<property name="Name" column="Clan_Name" unique-key="ClanNameConstraint" type="String"/>
<many-to-one name="ClanLeader" class="Player" />
</class>
You do not need to write assembly qualified class name in the mapping. Assembly and namespace attributes of hibernate-mapping element specify default namespace and assembly where NH tries to find specific class.

NHibernate mapping error SQL Server 2008 Express

I tried an example from NHibernate in Action book and when I try to run the app, it throws an exception saying "Could not compile the mapping document:
HelloNHibernate.Employee.hbm.xml"
Below is my code,
Employee.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="HelloNHibernate.Employee, HelloNHibernate" lazy="false" table="Employee">
<id name="id" access="field">
<generator class="native"/>
</id>
<property name="name" access="field" column="name"/>
<many-to-one access="field" name="manager" column="manager" cascade="all"/>
</class>
</hibernate-mapping>
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using System.Reflection;
using NHibernate.Cfg;
namespace HelloNHibernate
{
class Program
{
static void Main(string[] args)
{
CreateEmployeeAndSaveToDatabase();
UpdateTobinAndAssignPierreHenriAsManager();
LoadEmployeesFromDatabase();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
static void CreateEmployeeAndSaveToDatabase()
{
Employee tobin = new Employee();
tobin.name = "Tobin Harris";
using (ISession session = OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Save(tobin);
transaction.Commit();
}
Console.WriteLine("Saved Tobin to the database");
}
}
static ISession OpenSession()
{
if (factory == null)
{
Configuration c = new Configuration();
c.AddAssembly(Assembly.GetCallingAssembly());
factory = c.BuildSessionFactory();
}
return factory.OpenSession();
}
static void LoadEmployeesFromDatabase()
{
using (ISession session = OpenSession())
{
IQuery query = session.CreateQuery("from Employee as emp order by emp.name asc");
IList<Employee> foundEmployees = query.List<Employee>();
Console.WriteLine("\n{0} employees found:", foundEmployees.Count);
foreach (Employee employee in foundEmployees)
Console.WriteLine(employee.SayHello());
}
}
static void UpdateTobinAndAssignPierreHenriAsManager()
{
using (ISession session = OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
IQuery q = session.CreateQuery("from Employee where name='Tobin Harris'");
Employee tobin = q.List<Employee>()[0];
tobin.name = "Tobin David Harris";
Employee pierreHenri = new Employee();
pierreHenri.name = "Pierre Henri Kuate";
tobin.manager = pierreHenri;
transaction.Commit();
Console.WriteLine("Updated Tobin and added Pierre Henri");
}
}
}
static ISessionFactory factory;
}
}
Employee.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HelloNHibernate
{
class Employee
{
public int id;
public string name;
public Employee manager;
public string SayHello()
{
return string.Format("'Hello World!', said {0}.", name);
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0, Culture=neutral
PublicKeyToken=b77a5c561934e089"/>
</configSections>
<nhibernate>
<add key="hibernate.show_sql" value="false"/>
<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
<add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect"/>
<add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
<add key="hibernate.connection.connection_string" value="Server=(local)\SQLEXPRESS; Database=HelloNHibernate;Integrated Security=SSPI;"/>
</nhibernate>
</configuration>
Let's open the Matryoshka doll a bit further, and solve the other problem:
In this line:
<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0, Culture=neutral
PublicKeyToken=b77a5c561934e089"/>
you're missing a comma between "neutral" and "PublicKeyToken".
Give that a try.
Do you have a manager class and mapping defined? The
<many-to-one access="field" name="manager" column="manager" cascade="all"/>
line is looking for one. If the "manager" field is supposed to be an Employee, then you probably want:
<many-to-one access="field" name="manager" column="manager" class="HelloNHibernate.Employee, HelloNHibernate" cascade="all"/>
I think I see the problem now. The problem appears to be in this line:
<add key="hibernate.connection.connection_string" value="SQL2008EXPRESS" Database="HelloNHibernate;Integrated Security=SSPI;User Id=SQL2008"/>
The connection string is malformed, and it's throwing off the XML parser. Since the "value" attribute ends early, the XML parser thinks "Database=" is another XML attribute, but it's not one it recognizes, so it chokes. The solution is to fix the connection string.
The line should probably read:
<add key="hibernate.connection.connection_string" value="Server=(local)\SQLEXPRESS; Database=HelloNHibernate;Integrated Security=SSPI;"/>
This is assuming you're using Windows authentication; given that this is a learning project, that's probably the best way to go. If you're using SQL Server authentication, use this line instead:
<add key="hibernate.connection.connection_string" value="Server=(local)\SQLEXPRESS; Database=HelloNHibernate; User Id=theusername; Password=thepassword"/>
An aside: I don't think NHibernate 1.2.1GA has a SQL Server 2008 dialect. Instead, use NHibernate.Dialect.MsSql2005Dialect.