performance nhibernate criteria icriteria

performance - NHibernate-CreateCriteria vs CreateAlias



icriteria (3)

Suponiendo el siguiente escenario:

class Project{ public Job Job; } class Job{ public Name; }

Suponiendo 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 Trabajo y usarlo para acceder a Nombre, o podría crear un nuevo Criterio para la propiedad Trabajo y buscar por Nombre.

En cuanto al rendimiento, ¿hay alguna diferencia?


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 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 el primer CreateCriteria lo ejecuta devolverá la entidad "Categoría", por lo tanto, cuando el segundo CreateCriteria lo ejecute no encontrará la propiedad ProductStocks en la entidad "Categoría" y la consulta fallará.

Así que la forma 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 el primer CreateAlias ​​lo ejecuta, devuelve la entidad "Producto", cuando el segundo CreateCriteria se ejecuta, encontrará la propiedad ProductStocks en la entidad "Producto".

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 sea de ayuda.


createAlias ​​() devuelve criterios originales como resultado createCriteria () devuelve nuevos criterios construidos con createCriteria

diferencia será cuando los métodos de encadenamiento, por ejemplo,

cr.createAlias ​​(). add (Restrictions.ilike ("code", "abc")) agregará restricción a la entidad cr.createCriteria ("parent", "p"). add (Restrictions.ilike ("code", " abc ")) agregará restricción a su padre


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

sin embargo, tenga en cuenta que CreateAlias 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''