我最近开始使用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中实现这一点将非常感激。
答案 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>();
希望这有效..