Dear folks,
Let say... well, i'm a newbie to nHibernate, and hibernate it self,
Before i tell the story, let say i'm not a native English talker, so i apologizes at first.
Due to begin long thread, let me tell you that this thread contains:
- story behind my need
- what i want to achieve
- my questions
- class diagram image
- and object models and some config file as samples
Last place i worked some year ago, they used technology named hibernate, in their java based CMS, so as i see that useful, and i search for that in .net and found nHibernate...but i did none. after long time, several month ago, just once i start my work at here, one of my friend bring up me an exist idea, which were implemented, but in very bad shape, without support, and were left very unhappy customer, and as my friend research over it, i found out no one use the system. but, the shop owner are still welcome with a good new system, that can solve their need.
also some of those big ones, get their own customized software,...
the software is about sell/rent of land or houses in my country...
As i'm fast in C#, most of times, i'm one step in front of other, and if there are no extra, then i have free times to do my staff... So i start the project over the system, first i tried to do it in java, but the UI Editor, Component, code handling, Grids, made me to leave it behind and start new one on C#... (my country users are mostly windows user, and those who use iOS, they also install virtual machine and use windows. and Linux? just some folks, no need to think about it.
Know let get to the point of my question,
- As i said i were work on hibernate through java, though it was just on getting data, using pre-configured system, but my boss let me to store my samples, so i also had configuration file, and i config my application same to that, and config files are the old plain XML files.
- Next, as there were too many fields, shared and non-shared, i decide to normalize my tables, though it's not very normalized as i naturally don't do it with intend in mind, and mostly on 'one-to-many' data, not on 'one-to-one' data. so i found some sample which look useful, and i used 'Inheritance', i know i could map my data using normal binding with putting a 'List' or maybe even 'Entity' inside my class, but i didn't wanted hibernate to bring several separate list, which i later decide how to work with them, and slow the system, so i wanted to 'join' performs on SQL side, and binding happen in whole data together,
So i create BaseInfo
then House which extends BaseInfo , and so on
now, i done this,
- but i dont know how to bind data, in such a case and samples are not tell me if i do what, hibernate do what.
- second is i want you too look at my entity code and tell if i do the normalization in a wrong way.
- in future, i want to provide ability for shop manager, to share their data with other, so for example, if i come to you, and i say i want a house in one of X places, you can also search in other store data, but the issue is that searching other store data, will expose also owner info which will cause other shop manager, sell the house directly, and one will loss profit in here, so i'm not sure if i should separate user infos (and best way to bind it)? or i should keep it inside the class and just replace the values with shop owner infos?
![Dear folks,
Let say... well, i'm a newbie to nHibernate, and hibernate it self,
Before i tell the story, let say i'm not a native English talker, so i apologizes at first.
Due to begin long thread, let me tell you that this thread contains:
- story behind my need
- what i want to achieve
- my questions
- class diagram image
- and object models and some config file as samples
Last place i worked some year ago, they used technology named hibernate, in their java based CMS, so as i see that useful, and i search for that in .net and found nHibernate...but i did none. after long time, several month ago, just once i start my work at here, one of my friend bring up me an exist idea, which were implemented, but in very bad shape, without support, and were left very unhappy customer, and as my friend research over it, i found out no one use the system. but, the shop owner are still welcome with a good new system, that can solve their need.
also some of those big ones, get their own customized software,...
the software is about sell/rent of land or houses in my country...
As i'm fast in C#, most of times, i'm one step in front of other, and if there are no extra, then i have free times to do my staff... So i start the project over the system, first i tried to do it in java, but the UI Editor, Component, code handling, Grids, made me to leave it behind and start new one on C#... (my country users are mostly windows user, and those who use iOS, they also install virtual machine and use windows. and Linux? just some folks, no need to think about it.
Know let get to the point of my question,
- As i said i were work on hibernate through java, though it was just on getting data, using pre-configured system, but my boss let me to store my samples, so i also had configuration file, and i config my application same to that, and config files are the old plain XML files.
- Next, as there were too many fields, shared and non-shared, i decide to normalize my tables, though it's not very normalized as i naturally don't do it with intend in mind, and mostly on 'one-to-many' data, not on 'one-to-one' data. so i found some sample which look useful, and i used 'Inheritance', i know i could map my data using normal binding with putting a 'List' or maybe even 'Entity' inside my class, but i didn't wanted hibernate to bring several separate list, which i later decide how to work with them, and slow the system, so i wanted to 'join' performs on SQL side, and binding happen in whole data together,
So i create BaseInfo
then House which extends BaseInfo , and so on
now, i done this,
- but i dont know how to bind data, in such a case and samples are not tell me if i do what, hibernate do what.
- second is i want you too look at my entity code and tell if i do the normalization in a wrong way.
- in future, i want to provide ability for shop manager, to share their data with other, so for example, if i come to you, and i say i want a house in one of X places, you can also search in other store data, but the issue is that searching other store data, will expose also owner info which will cause other shop manager, sell the house directly, and one will loss profit in here, so i'm not sure if i should separate user infos (and best way to bind it)? or i should keep it inside the class and just replace the values with shop owner infos?
Codes:
public abstract class BaseInfo
{
private Guid _id;
private string _code;
private string _owner;
private PersonTitle _ownerTitle;
private string _country;
private string _state;
private string _city;
private string _address;
private string _phone;
private string _cellPhone1;
private string _cellPhone2;
private DateTime _issueDate;
private int _meter;
private string _dimensions;
private string _description;
public virtual Guid Id
{
get { return _id; }
set { _id = value; }
}
public virtual string Code
{
get { return _code; }
set { _code = value; }
}
public virtual string Owner
{
get { return _owner; }
set { _owner = value; }
}
public virtual PersonTitle OwnerTitle
{
get { return _ownerTitle; }
set { _ownerTitle = value; }
}
public virtual string Country
{
get { return _country; }
set { _country = value; }
}
public virtual string State
{
get { return _state; }
set { _state = value; }
}
public virtual string City
{
get { return _city; }
set { _city = value; }
}
public virtual string Address
{
get { return _address; }
set { _address = value; }
}
public virtual string Phone
{
get { return _phone; }
set { _phone = value; }
}
public virtual string CellPhone1
{
get { return _cellPhone1; }
set { _cellPhone1 = value; }
}
public virtual string CellPhone2
{
get { return _cellPhone2; }
set { _cellPhone2 = value; }
}
public virtual DateTime IssueDate
{
get { return _issueDate; }
set { _issueDate = value; }
}
public virtual int Meter
{
get { return _meter; }
set { _meter = value; }
}
public virtual string Dimensions
{
get { return _dimensions; }
set { _dimensions = value; }
}
public virtual string Description
{
get { return _description; }
set { _description = value; }
}
}
public abstract class House : BaseInfo
{
private HouseType _houseType;
private Direction _direction;
private byte _roomCount;
private Facility _facilities;
private string _otherFacilities;
private int _buildYear;
private bool _hasYard; //HaveYard???
public virtual HouseType HouseType
{
get { return _houseType; }
set { _houseType = value; }
}
public virtual Direction Direction
{
get { return _direction; }
set { _direction = value; }
}
public virtual byte RoomCount
{
get { return _roomCount; }
set { _roomCount = value; }
}
public virtual Facility Facilities
{
get { return _facilities; }
set { _facilities = value; }
}
public virtual string OtherFacilities
{
get { return _otherFacilities; }
set { _otherFacilities = value; }
}
public virtual int BuildYear
{
get { return _buildYear; }
set { _buildYear = value; }
}
public virtual bool HasYard
{
get { return _hasYard; }
set { _hasYard = value; }
}
}
public class RentHouse : House
{
private DoorType _doorType;
private decimal _mortgageAmount;
private decimal _rentAmount;
public DoorType DoorType
{
get { return _doorType; }
set { _doorType = value; }
}
public decimal MortgageAmount
{
get { return _mortgageAmount; }
set { _mortgageAmount = value; }
}
public decimal RentAmount
{
get { return _rentAmount; }
set { _rentAmount = value; }
}
}
public class SellHouse : House
{
private int _meterUnderBuilding;
private byte _floor;
private int _numberOfFloors;
private int _numberOfSections;//ps-fa: vahed
private string _document;
private float _shareOfSixPart;//ps-fa: dong
#region Loan
private decimal _loan;
private LoanType _loanType; //?????? mortgage / rent
private decimal _amount;
#endregion Loan
private decimal _cost;
private bool _exchange;
//TODO: Properties
}
public class Land : BaseInfo
{
}
public class Owner
{
// Should i seperate owners info?
// And how?
}
Here's the binding i used and research over it, but for simple data(binding may not be completely correct as i changed fields continuously):
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property">
<!-- assembly="BusinessTier" namespace="HassanFaghihi.StatesInstitution.BusinessTier.Model">-->
<class name="HassanFaghihi.StatesInstitution.BusinessTier.Model.BaseInfo, BusinessTier" table="base_info">
<!--<id name="Id" column="id">
<generator class="identity" />
</id>
<property name="Owner" column="owner" not-null="true"/>
<property name="Address" column="address" not-null="true"/>
<property name="Meter" column="meter"/>
<property name="Floor" column="floor"/>
<property name="Direction" column="direction"/>
<property name="RoomCount" column="room_count"/>
<property name="HouseType" column="house_type" not-null="true"/>
<property name="Facilities" column="facilities"/>
<property name="Description" column="description"/>-->
<id name="Id" column="id">
<generator class="guid"/>
</id>
<property name="Code" column="code"/>
<property name="Owner" column="owner"/>
<property name="OwnerTitle" column="owner_title"/>
<property name="Country" column="country"/>
<property name="State" column="state"/>
<property name="City" column="city"/>
<property name="Address" column="address"/>
<property name="Phone" column="phone"/>
<property name="CellPhone1" column="cell_phone_1"/>
<property name="CellPhone2" column="cell_phone_2"/>
<property name="IssueDate" column="issue_date"/>
<property name="Description" column="description"/>
</class>
</hibernate-mapping>
I use nHibernate 4.x, so i can use it same way i did long ago, using spring framwork...
Config:
<?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="dialect">NHibernate.Dialect.MySQL5Dialect</property>
<property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property>
<property name="connection.connection_string">Server=localhost;Database=statesinsititution;User ID=root;Password=a123;CharSet=latin1</property>
<!-- JDBC connection pool (use the built-in) -->
<!-- <property name="connection.pool_size">1</property> -->
<!-- SQL dialect -->
<!-- <property name="dialect">org.hibernate.dialect.HSQLDialect</property> -->
<!-- <property name="dialect">org.hibernate.dialect.MySQLDialect</property> -->
<!-- Enable Hibernate's automatic session context management -->
<!-- <property name="current_session_context_class">thread</property> -->
<!-- Disable the second-level cache -->
<!-- <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> -->
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="prepare_sql">true</property>
<!-- DB schema will be updated if needed -->
<property name="hbm2ddl.auto">update</property>
<property name="format_sql">true</property>
<mapping assembly="BusinessTier"/>
<!--<mapping assembly="StatesInstitution"/>-->
</session-factory>
</hibernate-configuration>
Session Manager:
public class HibernateUtil
{
private HibernateUtil(){}
private static readonly ISessionFactory SessionFactory = BuildSessionFactory();
private static ISessionFactory BuildSessionFactory()
{
try
{
var config = new Configuration();
config.Configure("hibernate.cfg.xml");
return config.BuildSessionFactory();
}
catch (Exception ex)
{
Console.WriteLine("Initial SessionFactory creation failed." + ex);
throw new TypeInitializationException(typeof (ISessionFactory).FullName, ex);
}
}
public static void PreInitialize()
{
GetSessionFactory();
}
internal static ISessionFactory GetSessionFactory()
{
return SessionFactory;
}
public static void Shutdown()
{
GetSessionFactory().Close();
}
}
Base DAO:
internal class BaseDao
{
public void Save(Object obj)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
session.Save(obj);
session.Transaction.Commit();
}
public void Update(Object obj)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
session.Merge(obj);
session.Transaction.Commit();
}
public void Delete(Object obj)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
session.Delete(obj);
session.Transaction.Commit();
}
public void SaveOrUpdate(Object obj)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
session.SaveOrUpdate(obj);
session.Transaction.Commit();
}
public Object Get(Type t, object id)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
Object obj = session.Get(t, id);
session.Transaction.Commit();
return obj;
}
public IList Get(Type type, String where, String orderby, int limit)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
String query = "from " + type.Name;
if (where.Length > 0)
query += " where " + where;
if (orderby.Length > 0)
query += " order by " + orderby;
Console.WriteLine("BaseDao-Query: " + query);
//ArrayList<User> list = (ArrayList<User>)session.createQuery("from User").list();
IList list = session.CreateQuery(query).SetMaxResults(limit).List();
session.Transaction.Commit();
return list;
}
}
Codes:
public abstract class BaseInfo
{
private Guid _id;
private string _code;
private string _owner;
private PersonTitle _ownerTitle;
private string _country;
private string _state;
private string _city;
private string _address;
private string _phone;
private string _cellPhone1;
private string _cellPhone2;
private DateTime _issueDate;
private int _meter;
private string _dimensions;
private string _description;
public virtual Guid Id
{
get { return _id; }
set { _id = value; }
}
public virtual string Code
{
get { return _code; }
set { _code = value; }
}
public virtual string Owner
{
get { return _owner; }
set { _owner = value; }
}
public virtual PersonTitle OwnerTitle
{
get { return _ownerTitle; }
set { _ownerTitle = value; }
}
public virtual string Country
{
get { return _country; }
set { _country = value; }
}
public virtual string State
{
get { return _state; }
set { _state = value; }
}
public virtual string City
{
get { return _city; }
set { _city = value; }
}
public virtual string Address
{
get { return _address; }
set { _address = value; }
}
public virtual string Phone
{
get { return _phone; }
set { _phone = value; }
}
public virtual string CellPhone1
{
get { return _cellPhone1; }
set { _cellPhone1 = value; }
}
public virtual string CellPhone2
{
get { return _cellPhone2; }
set { _cellPhone2 = value; }
}
public virtual DateTime IssueDate
{
get { return _issueDate; }
set { _issueDate = value; }
}
public virtual int Meter
{
get { return _meter; }
set { _meter = value; }
}
public virtual string Dimensions
{
get { return _dimensions; }
set { _dimensions = value; }
}
public virtual string Description
{
get { return _description; }
set { _description = value; }
}
}
public abstract class House : BaseInfo
{
private HouseType _houseType;
private Direction _direction;
private byte _roomCount;
private Facility _facilities;
private string _otherFacilities;
private int _buildYear;
private bool _hasYard; //HaveYard???
public virtual HouseType HouseType
{
get { return _houseType; }
set { _houseType = value; }
}
public virtual Direction Direction
{
get { return _direction; }
set { _direction = value; }
}
public virtual byte RoomCount
{
get { return _roomCount; }
set { _roomCount = value; }
}
public virtual Facility Facilities
{
get { return _facilities; }
set { _facilities = value; }
}
public virtual string OtherFacilities
{
get { return _otherFacilities; }
set { _otherFacilities = value; }
}
public virtual int BuildYear
{
get { return _buildYear; }
set { _buildYear = value; }
}
public virtual bool HasYard
{
get { return _hasYard; }
set { _hasYard = value; }
}
}
public class RentHouse : House
{
private DoorType _doorType;
private decimal _mortgageAmount;
private decimal _rentAmount;
public DoorType DoorType
{
get { return _doorType; }
set { _doorType = value; }
}
public decimal MortgageAmount
{
get { return _mortgageAmount; }
set { _mortgageAmount = value; }
}
public decimal RentAmount
{
get { return _rentAmount; }
set { _rentAmount = value; }
}
}
public class SellHouse : House
{
private int _meterUnderBuilding;
private byte _floor;
private int _numberOfFloors;
private int _numberOfSections;//ps-fa: vahed
private string _document;
private float _shareOfSixPart;//ps-fa: dong
#region Loan
private decimal _loan;
private LoanType _loanType; //?????? mortgage / rent
private decimal _amount;
#endregion Loan
private decimal _cost;
private bool _exchange;
//TODO: Properties
}
public class Land : BaseInfo
{
}
public class Owner
{
// Should i seperate owners info?
// And how?
}
Here's the binding i used and research over it, but for simple data(binding may not be completely correct as i changed fields continuously):
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property">
<!-- assembly="BusinessTier" namespace="HassanFaghihi.StatesInstitution.BusinessTier.Model">-->
<class name="HassanFaghihi.StatesInstitution.BusinessTier.Model.BaseInfo, BusinessTier" table="base_info">
<!--<id name="Id" column="id">
<generator class="identity" />
</id>
<property name="Owner" column="owner" not-null="true"/>
<property name="Address" column="address" not-null="true"/>
<property name="Meter" column="meter"/>
<property name="Floor" column="floor"/>
<property name="Direction" column="direction"/>
<property name="RoomCount" column="room_count"/>
<property name="HouseType" column="house_type" not-null="true"/>
<property name="Facilities" column="facilities"/>
<property name="Description" column="description"/>-->
<id name="Id" column="id">
<generator class="guid"/>
</id>
<property name="Code" column="code"/>
<property name="Owner" column="owner"/>
<property name="OwnerTitle" column="owner_title"/>
<property name="Country" column="country"/>
<property name="State" column="state"/>
<property name="City" column="city"/>
<property name="Address" column="address"/>
<property name="Phone" column="phone"/>
<property name="CellPhone1" column="cell_phone_1"/>
<property name="CellPhone2" column="cell_phone_2"/>
<property name="IssueDate" column="issue_date"/>
<property name="Description" column="description"/>
</class>
</hibernate-mapping>
I use nHibernate 4.x, so i can use it same way i did long ago, using spring framwork...
Config:
<?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="dialect">NHibernate.Dialect.MySQL5Dialect</property>
<property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property>
<property name="connection.connection_string">Server=localhost;Database=statesinsititution;User ID=root;Password=a123;CharSet=latin1</property>
<!-- JDBC connection pool (use the built-in) -->
<!-- <property name="connection.pool_size">1</property> -->
<!-- SQL dialect -->
<!-- <property name="dialect">org.hibernate.dialect.HSQLDialect</property> -->
<!-- <property name="dialect">org.hibernate.dialect.MySQLDialect</property> -->
<!-- Enable Hibernate's automatic session context management -->
<!-- <property name="current_session_context_class">thread</property> -->
<!-- Disable the second-level cache -->
<!-- <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> -->
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="prepare_sql">true</property>
<!-- DB schema will be updated if needed -->
<property name="hbm2ddl.auto">update</property>
<property name="format_sql">true</property>
<mapping assembly="BusinessTier"/>
<!--<mapping assembly="StatesInstitution"/>-->
</session-factory>
</hibernate-configuration>
Session Manager:
public class HibernateUtil
{
private HibernateUtil(){}
private static readonly ISessionFactory SessionFactory = BuildSessionFactory();
private static ISessionFactory BuildSessionFactory()
{
try
{
var config = new Configuration();
config.Configure("hibernate.cfg.xml");
return config.BuildSessionFactory();
}
catch (Exception ex)
{
Console.WriteLine("Initial SessionFactory creation failed." + ex);
throw new TypeInitializationException(typeof (ISessionFactory).FullName, ex);
}
}
public static void PreInitialize()
{
GetSessionFactory();
}
internal static ISessionFactory GetSessionFactory()
{
return SessionFactory;
}
public static void Shutdown()
{
GetSessionFactory().Close();
}
}
Base DAO:
internal class BaseDao
{
public void Save(Object obj)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
session.Save(obj);
session.Transaction.Commit();
}
public void Update(Object obj)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
session.Merge(obj);
session.Transaction.Commit();
}
public void Delete(Object obj)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
session.Delete(obj);
session.Transaction.Commit();
}
public void SaveOrUpdate(Object obj)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
session.SaveOrUpdate(obj);
session.Transaction.Commit();
}
public Object Get(Type t, object id)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
Object obj = session.Get(t, id);
session.Transaction.Commit();
return obj;
}
public IList Get(Type type, String where, String orderby, int limit)
{
ISession session = HibernateUtil.GetSessionFactory().OpenSession();
session.BeginTransaction();
String query = "from " + type.Name;
if (where.Length > 0)
query += " where " + where;
if (orderby.Length > 0)
query += " order by " + orderby;
Console.WriteLine("BaseDao-Query: " + query);
//ArrayList<User> list = (ArrayList<User>)session.createQuery("from User").list();
IList list = session.CreateQuery(query).SetMaxResults(limit).List();
session.Transaction.Commit();
return list;
}
}