2009-05-22 24 views
27

Giả sử các tình huống sau:NHibernate - CreateCriteria vs CreateAlias ​​

class Project{ 
    public Job Job; 
} 

class Job{ 
    public Name; 
} 

Giả sử tôi muốn sử dụng các API Tiêu chuẩn để tìm kiếm cho tất cả các dự án mà công việc có tên "sumthing".

Tôi có thể sử dụng CreateAlias ​​để tạo bí danh cho công việc và sử dụng bí danh đó để truy cập Tên hoặc tôi có thể tạo Tiêu chí mới cho thuộc tính Công việc và tìm kiếm theo Tên.

Hiệu suất khôn ngoan, có sự khác biệt nào không?

Trả lời

38

được các yêu cầu này thì sẽ không có sự khác biệt, SQL được tạo ra là như nhau: cho ánh xạ:

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

và các lớp

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

các tiêu chí các định nghĩa

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

tạo cùng một 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' 

lưu ý tuy nhiên rằng CreateAlias dựa trên ánh xạ để tạo ra các hiệp hội trong khi cuộc gọi CreateCriteria cho phép để xác định JoinType.

như vậy, các cuộc gọi

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

tạo những câu lệnh 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' 
+1

Nhưng bạn có thể chỉ định loại kết nối trong quá tải CreateAlias? CreateAlias ​​luôn luôn dường như mặc định để tham gia bên trong cho tôi ... ngay cả khi nhiều người-một cho phép nulls. – dotjoe

+4

Có với NH2 ++ CreateAlias ​​cũng cho phép chỉ định một JoinType ghi đè các liên kết được ánh xạ. Tôi đoán rằng kể từ khi CreateCriteria trả về một đối tượng ICriteria ("rooted" tại thực thể liên quan), có thể tạo các truy vấn (nâng cao) khác nhau do ICriteria được tạo ra có thể được thao tác theo nhiều cách. – Jaguar

7

createAlias ​​() trả về tiêu chí ban đầu như là kết quả createCriteria() trả về tiêu chí mới được xây dựng với createCriteria

khác biệt sẽ là khi các phương pháp chuỗi

cr.createAlias ​​(). Thêm (Restrictions.ilike ("code", "abc")) sẽ thêm hạn chế vào đối tượng cr.createCriteria ("parent", "p") thêm (Restrictions.ilike ("code", "abc")) sẽ thêm hạn chế vào phụ huynh

22

Để giải thích sự khác biệt giữa CreateCriteria và CreateAlias ​​trong NHibernate 2.0 + cho phép xem mô hình miền sau.

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

Bây giờ nếu bạn viết tiêu chí sau để bên tham gia những tổ chức này

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

Các tiêu chí ở trên không làm việc, bởi vì khi CreateCriteria đầu tiên chạy nó trở về "Thể loại" thực thể, do đó khi CreateCriteria thứ hai thực hiện nó không tìm thấy thuộc tính ProductStocks trong thực thể "Danh mục" và truy vấn sẽ không thành công.

Vì vậy, cách chính xác để viết tiêu chí này là

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

Khi CreateAlias ​​đầu tiên chạy nó trở về "sản phẩm" tổ chức nào, khi CreateCriteria thứ hai thực hiện nó sẽ tìm thấy ProductStocks bất động sản trong "sản phẩm" thực thể.

Vì vậy, TSQL sẽ như thế này.

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 

Tôi hy vọng điều này sẽ hữu ích.

+0

Điều này làm cho rất nhiều ý nghĩa và trả lời câu hỏi ban đầu. – Oliver

Các vấn đề liên quan