NHibernate-createCriteria vs CreateAlias
Asumiendo el siguiente escenario:
class Project{
public Job Job;
}
class Job{
public Name;
}
Asumiendo que quiero usar la API de Criterios para buscar todos los proyectos cuyo Trabajo tenga el nombre "sumthing".
Podría usar CreateAlias para crear un alias para Job y usarlo para acceder a Name, o podría crear un nuevo Criterio para la propiedad Job y buscar por Name.
En cuanto al rendimiento, ¿hay alguna diferencia?
3 answers
Dados estos requisitos no habría diferencia, el SQL generado es el mismo: para asignaciones:
<?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>
Y clases
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; }
}
Estas definiciones de criterios
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"));
Generar el mismo 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'
Tenga en cuenta sin embargo que el CreateAlias
se basa en las asignaciones para generar asociaciones, mientras que la llamada CreateCriteria
permite especificar JoinType
.
Entonces, estas llamadas
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"));
Generar estas sentencias 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'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-22 21:18:20
Para explicar la diferencia entre createCriteria y CreateAlias en NHibernate 2.0 + veamos el siguiente modelo de dominio.
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; }
}
Ahora si escribes los siguientes criterios para unir internamente estas entidades
var criteria = DetachedCriteria.For<Product>()
.CreateCriteria("Category", JoinType.InnerJoin)
.CreateCriteria("ProductStocks", "ps", JoinType.InnerJoin)
.Add(Restrictions.Le("ps.Stock",10));
Los criterios anteriores no funcionarán porque cuando se ejecuta el primer createCriteria devuelve la entidad "Category", por lo tanto, cuando se ejecuta el segundo createCriteria no encontrará la propiedad ProductStocks en la entidad "Category" y la consulta fallará.
Así que la manera correcta de escribir este criterio es
var criteria = DetachedCriteria.For<Product>()
.CreateAlias("Category", "c", JoinType.InnerJoin)
.CreateCriteria("ProductStocks", "ps", JoinType.InnerJoin)
.Add(Restrictions.Le("ps.Stock",10));
Cuando la primera CreateAlias la ejecuta devuelve la entidad "Product", cuando la segunda createCriteria la ejecuta encontrará la propiedad ProductStocks en la entidad "Product".
Así que el TSQL será así.
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
Espero que esto ayude.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-12 02:23:24
CreateAlias () devuelve los criterios originales como resultado createCriteria () devuelve nuevos criterios construidos con createCriteria
La diferencia será cuando los métodos de encadenamiento, por ejemplo,
Cr.createAlias().añadir (Restricciones.ilike ("código"," abc")) agregará restricción a la entidad cr.createCriteria("padre","p").añadir (Restricciones.ilike ("code"," abc")) agregará restricción a su padre
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-02 11:14:12