我需要一种方法来在Nhibernate中查询具有包含值的Dictionary属性的项目。
假设:
public class Item
{
public virtual IDictionary<int, string> DictionaryProperty {get; set;}
}
和映射:
public ItemMap()
{
HasMany(x => x.DictionaryProperty)
.Access.ReadOnlyPropertyThroughCamelCaseField(Prefix.Underscore)
.AsMap<string>(
index => index.Column("IDNumber").Type<int>(),
element => element.Column("TextField").Type<string>().Length(666)
)
.Cascade.AllDeleteOrphan()
.Fetch.Join();
}
我想查询字典值为“SomeText”的所有Item
。 Linq中的以下示例失败:
session.Query<Item>().Where(r => r.DictionaryProperty.Any(g => g.Value == "SomeText"))
有错误
cannot dereference scalar collection element: Value
那么有没有办法在NHibernate中实现这一目标? Linq不是独家要求,而是优先考虑。并不是说我对使用.ContainsKey
可以实现的词典键进行查询不感兴趣。 Φορthis相似但不相同
答案 0 :(得分:3)
处理IDictionary<TValueType, TValueType>
通常会带来更多问题而不是优势。一种方法解决方法,是引入一个新对象(我称之为MyWrapper),其属性为Key
和Value
(只是一个例子命名)。
这样我们必须1)创建新对象(MyWrapper),2)调整映射,就是这样。没有其他更改... 所以原始的东西(映射,属性)将起作用,因为我们将使用不同的(只读)属性进行查询
public class MyWrapper
{
public virtual int Key { get; set; }
public virtual string Value { get; set; }
}
物品现在有
public class Item
{
// keep the existing for Insert/Updae
public virtual IDictionary<int, string> DictionaryProperty {get; set;}
// map it
private IList<MyWrapper> _properties = new List<MyWrapper>();
// publish it as readonly
public virtual IEnumerable<MyWrapper> Properties
{
get { return new ReadOnlyCollection<MyWrapper>(_properties); }
}
}
现在我们将扩展映射:
HasMany(x => x.Properties)
.Access.ReadOnlyPropertyThroughCamelCaseField(Prefix.Underscore)
.Component(c =>
{
c.Map(x => x.Key).Column("IDNumber")
c.Map(x => x.Value).Column("TextField")
})
...
;
查询,将按预期工作:
session
.Query<Item>()
.Where(r =>
r.Properties.Any(g => g.Value == "SomeText")
)
注意:根据我的经验,此解决方法不应该是解决方法。这是首选方式。 NHibernate支持许多功能,但使用Objects可带来更多利润