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

相关问题