views:

194

answers:

2

Hello, I have simple situation (like on the image link text) and simple SQL query

SELECT  M.Name, 
          A.Name, 
          B.Name 
FROM Master M       LEFT JOIN DetailA A
ON M.DescA = A.Id   LEFT JOIN DetailB B
ON M.DescB = B.Id

How to achive the same effect in nHibernate using CriteriaAPI ?

I have something like this:

public class Employee : ClassBase, IContactData
{
    public virtual string FirstName { get; set; }
    public virtual string MiddleName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string NickName { get; set; }
    public virtual string Login { get; set; }
    public virtual string Password { get; set; }
    public virtual string ContactPerson { get; set; }
    public virtual string PESEL { get; set; }
    public virtual string IdentificationNo { get; set; }
    public virtual string NIP { get; set; }
    public virtual string Description { get; set; }
    public virtual string Profession { get; set; }
    public virtual byte[] Photo { get; set; }
    public virtual DateTime? BirthDate { get; set; }
    public virtual Boolean SpecialUser { get; set; }
    public virtual Boolean Sex { get; set; }
    public virtual Item Gender { get; set; }
    public virtual Item Position { get; set; }
    public virtual Item Status { get; set; }
    public virtual Item Nation { get; set; }
    public virtual Item Education { get; set; }
    public virtual Item JobType { get; set; }
    public virtual ISet<Address> Addresses { get; set; }
}

public class Item : ClassBase
{

    public virtual int ItemCode { get; set; }
    public virtual int DictCode{ get; set;}
    public virtual string Description{ get; set;}

    public override string ToString()
    {
        return Description;
    }
}

public class Address : ClassBase
{
    public virtual string Description { get; set; }
    public virtual string District { get; set; }
    public virtual string Community { get; set; }
    public virtual string City { get; set; }
    public virtual string Street { get; set; }
    public virtual string PostalCode { get; set; }
    public virtual string HouseNo { get; set; }
    public virtual string FlatNo { get; set; }
    public virtual Boolean Official { get; set; }
    public virtual Item Country { get; set; }
    public virtual Item Region { get; set; }
}

Mappings:

<property name="FirstName"        column="FIRST_NAME"         type="string"   length="50"    not-null="true"/>
<property name="MiddleName"       column="MIDDLE_NAME"        type="string"   length="50"    not-null="false"/>
<property name="LastName"         column="LAST_NAME"          type="string"   length="50"    not-null="true"/>
<property name="NickName"         column="NICKNAME"           type="string"   length="50"    not-null="false"/>
<property name="Login"            column="LOGIN"              type="string"   length="30"    not-null="false"/>
<property name="Password"         column="PASSWORD"           type="string"   length="100"   not-null="false"/>
<property name="ContactPerson"    column="CONTACT_PERSON"     type="string"   length="250"   not-null="false"/>
<property name="PESEL"            column="PESEL"              type="string"   length="11"    not-null="false"/>
<property name="IdentificationNo" column="IDENTIFICATION_NO"  type="string"   length="12"    not-null="false"/>
<property name="NIP"              column="NIP"                type="string"   length="11"    not-null="false"/>
<property name="Description"      column="DESCRIPTION"        type="string"   length="1000"  not-null="false"/>
<property name="Profession"       column="PROFESSION"         type="string"   length="150"   not-null="false"/>
<property name="BirthDate"        column="BIRTH_DATE"         type="DateTime"                not-null="false"/>
<property name="Photo"            column="PHOTO"              type="BinaryBlob"              not-null="false"/>
<property name="Sex"              column="SEX"                type="Boolean"                 not-null="false"/>
<property name="SpecialUser"      column="SPECIAL_USER"       type="Boolean"                 not-null="false"/>

<many-to-one name="Gender"        column="DIC_GENDER"         not-null="false" class="DomainModel.ERP.Item,DomainModel" />
<many-to-one name="Position"      column="DIC_POSITION"       not-null="false" class="DomainModel.ERP.Item,DomainModel" />
<many-to-one name="Status"        column="DIC_STATUS"         not-null="false" class="DomainModel.ERP.Item,DomainModel" />
<many-to-one name="Nation"        column="DIC_NATION"         not-null="false" class="DomainModel.ERP.Item,DomainModel" />
<many-to-one name="Education"     column="DIC_EDUCATION"      not-null="false" class="DomainModel.ERP.Item,DomainModel" />
<many-to-one name="JobType"       column="DIC_JOB_TYPE"       not-null="false" class="DomainModel.ERP.Item,DomainModel" />

<set name="Addresses" table="TBL_ADDRESS" generic="true">
  <key column="FK_EMPLOYEE" />
  <one-to-many class="DomainModel.ERP.HRM.Address,DomainModel"/>
</set>

<property name="ItemCode"         column="ITEM_CODE"          type="integer"  not-null="true"/>
<property name="DictCode"         column="TABLE_CODE"         type="integer"  not-null="true"/>
<property name="Description"      column="NAME"               type="string"   length="200"   not-null="true"/>

<version  name="Version"      column="VERSION"       type="integer"  unsaved-value="0"/>
<property name="Description"  column="DESCRIPTION"   type="string"   length="1000"  not-null="false"/>
<property name="District"     column="DISTRICT"      type="string"   length="15"    not-null="false"/>
<property name="Community"    column="COMMUNITY"     type="string"   length="150"   not-null="false"/>
<property name="City"         column="CITY"          type="string"   length="150"   not-null="true"/>
<property name="Street"       column="STREET"        type="string"   length="150"   not-null="true"/>
<property name="PostalCode"   column="POSTAL_CODE"   type="string"   length="10"    not-null="false"/>
<property name="HouseNo"      column="HOUSENO"       type="string"   length="20"    not-null="true"/>
<property name="FlatNo"       column="FLATNO"        type="string"   length="20"    not-null="false"/>
<property name="Official"     column="IS_OFFICIAL"   type="Boolean"                 not-null="true"/>

<many-to-one name="Country"           column="DIC_COUNTRY"      not-null="false"  class="DomainModel.ERP.Item,DomainModel" />
<many-to-one name="Region"            column="DIC_REGION"       not-null="false"  class="DomainModel.ERP.Item,DomainModel" />

I need :

  1. Retrive data to my grid Control
    - FirstName,
    - LastName,
    - NIP,
    - Position.Description,
    - Education.Description,
    - JobType.Description,
    - Country.Description - from Addresses where Address.Official is true,
    - Street - from Addresses where Address.Official is true,
    - HouseNo - from Addresses where Address.Official is true,
    - FlatNo - from Addresses where Address.Official is true.
  1. Retrive data to another grid Control
    - FirstName,
    - LastName,
    - NIP,
    - Position.Description,
    - Education.Description,
    - JobType.Description.

and the most important think. I want to do this using only one SELECT statement. Now for point 1 I use NamedSQLQuery and everything is working grate but for simplest situation I want use CriteriaAPI.

Also for point 1 and 2 I have DTO classes and I transform result of query to this classes.

I can do this by GetAllEmployees() but many properties is Lazy Loaded and doing that I have a huge trafic between application and database. I can change these properties to Eager Loading but in my opinion there is too much data to retrive which I don't need.

+1  A: 

My advice for this type of situation - where you want to display a grid with data from multiple entities, just create an sql view and map that with NH.

You will be much happier in the long run.

sirrocco
+1  A: 

I've found my solution :)

var master = DetachedCriteria.For<Master>()
        .CreateAlias("DetailA", "detA", JoinType.LeftOuterJoin)
        .CreateAlias("DetailB", "detB", JoinType.LeftOuterJoin)
        .SetProjection
        (
            Projections.ProjectionList()
            .Add(Projections.Property("Id"), "Id")
            .Add(Projections.Property("Name"), "MasterName")
            .Add(Projections.Property("detA.Name"), "DetailAName")
            .Add(Projections.Property("detB.Name"), "DetailBName")
        )
        .SetResultTransformer(Transformers.AliasToBean(typeof (MasterDTO)));

class MasterDTO
{
    public virtual int Id {get;set;}
    public virtual string MasterName {get;set;}
    public virtual string DetailAName {get;set;}
    public virtual string DetailBName {get;set;}

    public MasterDTO()
    {}

    public MasterDTO(int id, string mastername, string detailaname, string detailbname)
    {
        Id = id;
        MasterName = mastername;
        DetailAName = detailaname;
        DetailBName = detailbname;
    }
}