3

我最近開始使用NHibernate,並且在實現域模型時遇到了一些麻煩。流利的NHibernate和過濾一對多關係查詢需要多個連接?

我在尋找的是一種過濾項目及其在特定DataStore上的ItemData集合之間的關係的方法。 DataStore可以是全局的,在這種情況下,它們總是返回,或者是特定於用戶身份(基於應用程序實例)。

SELECT * FROM Items i 
INNER JOIN ItemData id ON (i.ItemId=id.ItemId) 
LEFT OUTER JOIN Users u ON (id.UserId=u.UserId) 
LEFT OUTER JOIN DataStore ds ON (id.DataStoreId=ds.DataStoreId) 
WHERE ds.IsGlobal = 1 OR ds.UserId = @userId 

數據庫結構:

DataStore: 
- DataStoreId (PK) 
- Name 
- Weight 
- UserId 
- IsGlobal 

Item: 
- ItemId (PK) 
- ... (non-nullable fields) 

ItemData: 
- ItemDataId (PK) 
- ItemId 
- DataStoreId 
- ... (nullable fields) 

領域模型:

public class ItemMap : ClassMap<Item> 
{ 
    public ItemMap() 
    { 
     Id(x => x.Id, "ItemId"); 
     HasMany(x => x.Data) 
      .KeyColumn("ItemId") 
      .ApplyFilter<ItemDataFilter>(..?) 
      .Cascade.AllDeleteOrphan(); 
    } 
} 

的基本原理是去取的ItemData

在SQL中可以使用簡單的查詢來完成每個數據存儲行,並加入各自DataStore的權重字段上的每列(第一個非空值按重量排序)。

對於如何以及如何在NHibernate中實現這一點有所瞭解將非常感謝。

回答

5

繼承人我發現自己以防別人正在尋找這些信息。

1.創建一個自定義過濾器:

public class ItemDataFilter : FilterDefinition 
{ 
    public ItemDataFilter() 
    { 
     WithName("ItemDataFilter").WithCondition("Data.DataStoreId == :DataStoreId").AddParameter("DataStoreId", NHibernate.NHibernateUtil.Int32); 
    } 
} 

2.Modify的功能NHibernate屬性映射(與.ApplyFilter <>()):

HasMany(x => x.Data) 
    .KeyColumn("ItemId") 
    .ApplyFilter<ItemDataFilter>() 
    .Cascade.AllDeleteOrphan(); 

3.In你的倉庫啓用過濾器並將其設置爲當前會話的屬性:

public IList<Item> GetItemsByDataStore(int DataStoreId) 
    { 
    using (var session = NHibernateHelper.OpenSession()) 
    { 
     session.EnableFilter("ItemDataFilter").SetParameter("DataStoreId", DataStoreId); 
     return session.CreateCriteria(typeof(Item)).List<Item>(); 
    } 
} 

另一種方法這將是獲取每個Item的所有ItemData並添加另一個執行此過濾的非映射屬性。

1

你可以用一個簡單的查詢也做到這一點使用HQL。您的HQL語句的語法如下:

Session.CreateQuery(hqlQuery).List(); 

你hqlQuery將是這樣的:

var hqlQuery= string.Format("select i from Items as i inner join i.ItemData left join Users u left join DataStire ds where u.UserId=i.UserId and ds.DataStoreId=i.DataStoreId and (ds.IsGlobal=1 or ds.UserId='{0}')",userId); 

Session.CreateQuery(hqlQuery).List<Item>(); 

希望這個作品..

+0

謝謝,但我希望這種關係可以作爲模型的一部分而不是通過自定義查詢來表示。如果我例如獲取一個項目,我希望使用此規則過濾ItemData的集合,而無需再次獲取它。 – magix 2011-02-27 14:53:49

+0

以及你可以隨時在相同的語句中添加語句。只需創建一個stringbuilder類並追加基本語句,然後在您的過濾條件和您的訂購條件下添加where子句(如果需要)。 – Baz1nga 2011-02-28 03:26:48

相關問題