流畅的NHibernate和过滤需要多个连接的查询的一对多关系?

时间:2011-02-27 02:17:49

标签: nhibernate fluent-nhibernate nhibernate-mapping filtering nhibernate-criteria

我最近开始使用NHibernate,并且在实现进一步概述的域模型时遇到了一些麻烦。

我正在寻找的是一种过滤Item和它在特定DataStore上的ItemData集合之间关系的方法。 DataStore是全局的,在这种情况下,它们总是返回,或者特定于用户身份(基于应用程序实例)。

在SQL中,这可以使用简单的查询来完成:

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

基本理论是每个DataStore获取一个ItemData行,并在相应DataStore的权重字段上连接每个列(按权重排序的第一个非空值)。

了解是否以及如何在NHibernate中实现这一点将非常感激。

2 个答案:

答案 0 :(得分:5)

如果其他人正在寻找这些信息,那就是我发现自己。

1.创建自定义过滤器:

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

2.修改您的Fluent NHibernate属性映射(使用.ApplyFilter&lt;&gt;()):

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

3.在您的存储库中启用过滤器并为当前会话设置其属性:

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 :(得分: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>();

希望这有效..