NHibernate - CreateCriteria 与 CreateAlias

发布于 2024-07-21 05:30:50 字数 269 浏览 9 评论 0原文

假设以下场景:

class Project{
   public Job Job;
}

class Job{
   public Name;
}

假设我想使用 Criteria API 搜索 Job 名称为“sumthing”的所有项目。

我可以使用 CreateAlias 为 Job 创建别名并使用它来访问 Name,或者我可以为属性 Job 创建一个新条件并按 Name 进行搜索。

性能方面,有什么区别吗?

Assuming the following scenario:

class Project{
   public Job Job;
}

class Job{
   public Name;
}

Assuming I want to use the Criteria API to search for all projects whose Job has the name "sumthing".

I could use the CreateAlias to create an alias for Job and use it to access Name, or I could create a new Criteria for the property Job and search by Name.

Performance wise, is there any difference?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

久伴你 2024-07-28 05:30:50

考虑到这些要求,没有什么区别,生成的 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'

given these requirements there would be no difference, the generated SQL is the same:
for mappings:

    <?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>

and classes

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

these criteria definitions

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"));

generate the same 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'

note however that the CreateAlias relies on the mappings to generate associations whereas the CreateCriteria call allows to specify JoinType.

so, these calls

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"));

generate these SQL statements

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'
像极了他 2024-07-28 05:30:50

为了解释 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; }
}   

现在,如果您编写以下条件来内部联接这些实体,则

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

上述条件将不起作用,因为当第一个 CreateCriteria 运行时,它返回“Category”实体,因此当第二个 CreateCriteria 执行时,它不会在“Category”实体中找到属性 ProductStocks,并且查询将失败。

因此,编写此条件的正确方法是,

var criteria = DetachedCriteria.For<Product>()
                .CreateAlias("Category", "c", JoinType.InnerJoin)
                .CreateCriteria("ProductStocks", "ps", JoinType.InnerJoin)
                .Add(Restrictions.Le("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 

我希望这个能帮上忙。

To explain the difference between CreateCriteria and CreateAlias in NHibernate 2.0 + lets see the following domain model.

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

Now if you write following criteria to inner join these entities

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

The above criteria wont work because when the first CreateCriteria runs it return "Category" entity, therefore when the second CreateCriteria execute it wont find property ProductStocks in the "Category" entity and the query will fail.

So the correct way to write this criteria is

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

When the first CreateAlias runs it return "Product" entity, when the second CreateCriteria execute it will find property ProductStocks in the "Product" entity.

So the TSQL will be like this.

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 

I hope this will help.

卷耳 2024-07-28 05:30:50

createAlias() 返回原始标准作为结果
createCriteria() 返回使用 createCriteria 构造的新标准,

差异在于当链接方法例如

cr.createAlias().add(Restrictions.ilike("code","abc")) 将为实体添加限制 时
cr.createCriteria("parent","p").add(Restrictions.ilike("code","abc")) 将为其父级添加限制

createAlias() returns original criteria as is result
createCriteria() returns new criteria constructed with createCriteria

difference will be when chaining methods e.g.

cr.createAlias().add(Restrictions.ilike("code","abc")) will add restriction to entity
cr.createCriteria("parent","p").add(Restrictions.ilike("code","abc")) will add restriction to its parent

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文