4

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

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

在 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 中实现这一点的见解将不胜感激。

4

2 回答 2

5

这是我自己发现的,以防其他人正在寻找此信息。

1.创建自定义过滤器:

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

2.修改您的 Fluent NHibernate 属性映射(使用 .ApplyFilter<>()):

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 并添加另一个执行此过滤的非映射属性。

于 2011-02-28T10:14:55.387 回答
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>();

希望这有效..

于 2011-02-27T08:10:11.017 回答