Подтвердить что ты не робот

NHibernate - CreateCriteria против CreateAlias

Предполагая следующий сценарий:

class Project{
   public Job Job;
}

class Job{
   public Name;
}

Предполагая, что я хочу использовать API критериев для поиска всех проектов, чей Иов имеет имя "sumthing".

Я мог бы использовать CreateAlias ​​для создания псевдонима для Job и использовать его для доступа к Name, или я мог бы создать новый критерий для свойства Job и search by Name.

Производительность мудрая, есть ли разница?

4b9b3361

Ответ 1

Учитывая эти требования, не было бы никакой разницы, сгенерированный SQL был бы таким же: для отображений:

    <?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="Project" table="Project">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="Id" sql-type="int" not-null="true" unique="true"/>
            <generator class="native" />
        </id>
        <many-to-one name="Job" column="FK_JobId" cascade="save-update" not-null="true" />
    </class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="Job" table="Job">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="Id" sql-type="int" not-null="true" unique="true"/>
            <generator class="native" />
        </id>
        <property name="Name" type="String">
            <column name="Name" sql-type="nvarchar" length="50" not-null="true"/>
        </property>
    </class>
</hibernate-mapping>

и классы

public class Project
    {
        public Project() { }

        public virtual int Id { get; set; }

        public virtual Job Job { get; set; }
    }
public class Job
    {
        public Job() { }

        public virtual int Id { get; set; }

        public virtual String Name { get; set; }
    }

эти определения критериев

ICriteria criteriacrit = session
  .CreateCriteria(typeof (Project))
  .CreateCriteria("Job", "job")
  .Add(Restrictions.Eq("job.Name", "sometextA"));

ICriteria aliascrit = session
  .CreateCriteria(typeof (Project))
  .CreateAlias("Job", "job")
  .Add(Restrictions.Eq("job.Name", "sometextB"));

создать тот же SQL

SELECT 
  this_.Id as Id2_1_, 
  this_.FK_JobId as FK2_2_1_, 
  job1_.Id as Id1_0_, 
  job1_.Name as Name1_0_ 
FROM 
  Project this_ 
  inner join Job job1_ 
    on this_.FK_JobId=job1_.Id 
WHERE job1_.Name = @p0; @p0 = 'sometextA'

SELECT 
  this_.Id as Id2_1_, 
  this_.FK_JobId as FK2_2_1_, 
  job1_.Id as Id1_0_, 
  job1_.Name as Name1_0_ 
FROM
  Project this_ 
  inner join Job job1_ 
    on this_.FK_JobId=job1_.Id 
WHERE job1_.Name = @p0; @p0 = 'sometextB'

обратите внимание, однако, что CreateAlias полагается на сопоставления для генерации ассоциаций, тогда как вызов CreateCriteria позволяет указать JoinType.

поэтому эти вызовы

ICriteria criteriacrit = session
  .CreateCriteria(typeof(Project))
  .CreateCriteria("Job",JoinType.LeftOuterJoin)
  .Add(Restrictions.Eq("Name", "sometextA"));

ICriteria aliascrit = session
  .CreateCriteria(typeof (Project))
  .CreateAlias("Job", "job")
  .Add(Restrictions.Eq("job.Name", "sometextB"));

сгенерировать эти операторы SQL

SELECT 
  this_.Id as Id2_1_, 
  this_.FK_JobId as FK2_2_1_, 
  job1_.Id as Id1_0_, 
  job1_.Name as Name1_0_ 
FROM 
  Project this_ 
  **left outer** join Job job1_
    on this_.FK_JobId=job1_.Id 
WHERE job1_.Name = @p0; @p0 = 'sometextA'

SELECT 
  this_.Id as Id2_1_, 
  this_.FK_JobId as FK2_2_1_, 
  job1_.Id as Id1_0_, 
  job1_.Name as Name1_0_ 
FROM Project this_ 
  **inner join** Job job1_ 
    on this_.FK_JobId=job1_.Id 
WHERE job1_.Name = @p0; @p0 = 'sometextB'

Ответ 2

Чтобы объяснить разницу между CreateCriteria и CreateAlias ​​в NHibernate 2.0 +, можно увидеть следующую модель домена.

public class Product
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; set; }
    public virtual decimal Price { get; set; }
    public virtual Category Category { get; set; }
    public virtual IList<ProductStock> ProductStocks { get; set; }
}

public class Category
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; set; }
    public virtual IList<Product> Products { get; set; }
}

public class ProductStock
{
    public virtual int Id { get; private set; }
    public virtual Product Product { get; set; }
    public virtual string WarehouseName { get; set; }
    public virtual int Stock { get; set; }
}   

Теперь, если вы пишете следующие критерии для внутреннего соединения этих объектов

var criteria = DetachedCriteria.For<Product>()
                .CreateCriteria("Category", JoinType.InnerJoin)
                .CreateCriteria("ProductStocks", "ps", JoinType.InnerJoin)
                .Add(Restrictions.Le("ps.Stock",10));

Вышеприведенные критерии не будут работать, потому что, когда первый CreateCriteria запускает его, возвращается объект "Категория", поэтому, когда второй CreateCriteria выполнит его, не найдет свойство ProductStocks в объекте "Категория" и запрос не будет выполнен.

Таким образом, правильный способ записи этого критерия -

var criteria = DetachedCriteria.For<Product>()
                .CreateAlias("Category", "c", JoinType.InnerJoin)
                .CreateCriteria("ProductStocks", "ps", JoinType.InnerJoin)
                .Add(Restrictions.Le("ps.Stock",10));

Когда первый CreateAlias ​​запускает его, возвращает объект "Продукт", когда второй CreateCriteria выполнит его, найдет свойство ProductStocks в объекте "Продукт".

Итак, TSQL будет таким.

SELECT this_.ProductID     as ProductID8_2_,
       this_.Name          as Name8_2_,
       this_.Price         as Price8_2_,
       this_.CategoryID    as CategoryID8_2_,
       ps2_.ProductStockID as ProductS1_9_0_,
       ps2_.Stock          as Stock9_0_,
       ps2_.ProductID      as ProductID9_0_,
       ps2_.WarehouseID    as Warehous4_9_0_,
       c1_.CategoryID      as CategoryID0_1_,
       c1_.Name            as Name0_1_
FROM   [Product] this_
       inner join [ProductStock] ps2_ on this_.ProductID = ps2_.ProductID
       inner join [Category] c1_ on this_.CategoryID = c1_.CategoryID
WHERE  ps2_.Stock <= 10 

Надеюсь, это поможет.

Ответ 3

createAlias ​​() возвращает исходные критерии, как результат createCriteria() возвращает новые критерии, построенные с помощью createCriteria

разница будет заключаться в том, что методы цепочки, например

cr.createAlias ​​(). add (Restrictions.ilike( "code", "abc" )) добавит ограничение сущности cr.createCriteria( "parent", "p" ). add (Restrictions.ilike( "code", "abc" )) добавит ограничение на родительский