Свойства соединения и проекции NHibernate - PullRequest
2 голосов
/ 27 мая 2010

У меня простая ситуация (как на картинке текст ссылки ) и простой запрос SQL

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

Как добиться того же эффекта в nHibernate с помощью CriteriaAPI?

У меня есть что-то вроде этого:

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; }
}

Отображения:

<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" />

Мне нужно:

  1. Извлечение данных в мою сетку. Control
  1. Извлечение данных в другую сетку. Control

и самое главное подумать. Я хочу сделать это, используя только один оператор SELECT. Теперь для пункта 1 я использую NamedSQLQuery, и все работает отлично, но для простейшей ситуации я хочу использовать CriteriaAPI.

Также для пунктов 1 и 2 у меня есть классы DTO, и я преобразовываю результат запроса в эти классы.

Я могу сделать это с помощью GetAllEmployees (), но многие свойства - это Lazy Loaded, и я получаю огромный трафик между приложением и базой данных. Я могу изменить эти свойства на Eager Loading, но, по моему мнению, слишком много данных для извлечения, которые мне не нужны.

Ответы [ 2 ]

7 голосов
/ 28 мая 2010

Я нашел свое решение:)

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;
    }
}
5 голосов
/ 28 мая 2010

Мой совет для ситуации такого типа - когда вы хотите отобразить сетку с данными из нескольких объектов, просто создайте представление SQL и сопоставьте его с NH.

Вы будете намного счастливее в долгосрочной перспективе.

...