Performance NHibernate-CreateCriteria与CreateAlias

Performance NHibernate-CreateCriteria与CreateAlias,performance,nhibernate,criteria,icriteria,Performance,Nhibernate,Criteria,Icriteria,假设出现以下情况: class Project{ public Job Job; } class Job{ public Name; } 假设我想使用CriteriaAPI搜索所有作业名为“sumthing”的项目 我可以使用CreateAlias为作业创建别名并使用它访问名称,也可以为属性作业创建新条件并按名称搜索 就性能而言,有什么区别吗?考虑到这些要求没有区别,生成的SQL是相同的: 对于映射: <?xml version="1.0" encoding="ut

假设出现以下情况:

class Project{
   public Job Job;
}

class Job{
   public Name;
}
假设我想使用CriteriaAPI搜索所有作业名为“sumthing”的项目

我可以使用CreateAlias为作业创建别名并使用它访问名称,也可以为属性作业创建新条件并按名称搜索


就性能而言,有什么区别吗?

考虑到这些要求没有区别,生成的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>
这些标准定义

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'
createAlias()返回原始条件作为结果 createCriteria()返回使用createCriteria构造的新条件

不同之处在于链接方法,例如

cr.createAlias().add(Restrictions.ilike(“code”、“abc”)将向实体添加限制
cr.createCriteria(“parent”,“p”).add(Restrictions.ilike(“code”,“abc”))将向其父级添加限制

,以解释NHibernate 2.0+中createCriteria和CreateAlias之间的差异。请参见以下域模型

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; }
}   
公共类产品
{
公共虚拟整数Id{get;private set;}
公共虚拟字符串名称{get;set;}
公共虚拟十进制价格{get;set;}
公共虚拟类别{get;set;}
公共虚拟IList ProductStocks{get;set;}
}
公共类类别
{
公共虚拟整数Id{get;private set;}
公共虚拟字符串名称{get;set;}
公共虚拟IList产品{get;set;}
}
公共类产品库存
{
公共虚拟整数Id{get;private set;}
公共虚拟产品产品{get;set;}
公共虚拟字符串WarehouseName{get;set;}
公共虚拟整数股票{get;set;}
}   
现在,如果您编写以下条件来内部连接这些实体

var criteria = DetachedCriteria.For<Product>()
                .CreateCriteria("Category", JoinType.InnerJoin)
                .CreateCriteria("ProductStocks", "ps", JoinType.InnerJoin)
                .Add(Restrictions.Le("ps.Stock",10));
var-criteria=DetachedCriteria.For()
.CreateCriteria(“类别”,JoinType.InnerJoin)
.CreateCriteria(“ProductStocks”、“ps”、JoinType.InnerJoin)
.增加(限制条款(ps.Stock),10);
上述条件不起作用,因为当第一个CreateCriteria运行时,它返回“Category”实体,因此当第二个CreateCriteria执行时,它不会在“Category”实体中找到property ProductStocks,查询将失败

所以写这个标准的正确方法是

var criteria = DetachedCriteria.For<Product>()
                .CreateAlias("Category", "c", JoinType.InnerJoin)
                .CreateCriteria("ProductStocks", "ps", JoinType.InnerJoin)
                .Add(Restrictions.Le("ps.Stock",10));
var-criteria=DetachedCriteria.For()
.CreateAlias(“类别”、“c”、JoinType.InnerJoin)
.CreateCriteria(“ProductStocks”、“ps”、JoinType.InnerJoin)
.增加(限制条款(ps.Stock),10);
第一个CreateAlias运行时返回“Product”实体,第二个CreateCriteria执行时将在“Product”实体中找到属性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 
选择此.ProductID作为ProductID8\u 2\,
此名称为Name8\u 2\u,
这个价格等于价格8,2,,
该类别为第8类,
ps2。ProductStockID为ProductS1\u9\u0,
ps2.库存为库存9\u 0,
ps2\u.ProductID为ProductID9\u 0\u,
ps2.仓库ID作为仓库4、9、0、,
c1.类别ID为类别D0,
c1.名称为名称0\u 1_
从[产品]这个_
内部联接[ProductStock]ps2\u在此\u.ProductID=ps2\u.ProductID上
内部联接[Category]c1_u在此_u.CategoryID=c1_g.CategoryID上

其中ps2_uu2;.Stock,但您可以在CreateAlias重载中指定联接类型?CreateAlias对我来说似乎总是默认为内部联接…即使多对一允许空值。是的,在NH2++中,CreateAlias还允许指定一个JoinType来覆盖映射的关联。我猜想,由于CreateCriteria返回一个ICriteria对象(“根”在关联实体),因此可能会生成不同的(高级)查询,因为生成的ICriteria可以以多种方式操作。这很有意义,并回答了最初的问题。
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