Nhibernate查询具有包含值的Dictionary属性的项目

Mih*_*gos 5 nhibernate fluent-nhibernate linq-to-nhibernate nhibernate-criteria

我需要一种方法来在Nhibernate中查询具有包含值的Dictionary属性的项目.

假设:

public class Item
{
     public virtual IDictionary<int, string> DictionaryProperty {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

和映射:

    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();
    }
Run Code Online (Sandbox Code Playgroud)

我想查询所有Item具有字典值"SomeText"的s.Linq中的以下示例失败:

session.Query<Item>().Where(r => r.DictionaryProperty.Any(g => g.Value == "SomeText"))
Run Code Online (Sandbox Code Playgroud)

有错误

cannot dereference scalar collection element: Value
Run Code Online (Sandbox Code Playgroud)

那么在NHibernate中有没有办法实现这一点?Linq不是独家要求,而是优先考虑.并不是说我对查询可以使用的字典不感兴趣.ContainsKey.Φορ 是相似但不相同的

Rad*_*ler 4

处理IDictionary<TValueType, TValueType>通常带来的问题多于优点。一种解决方法是引入一个具有属性和(只是示例命名)的新对象(我将其称为 MyWrapper)KeyValue

这样我们必须 1) 创建新对象 (MyWrapper),2) 调整映射,仅此而已。没有其他变化......所以原始的东西(映射,属性)将起作用,因为我们将使用不同的(只读)属性进行查询

public class MyWrapper
{
    public virtual int Key { get; set; }
    public virtual string Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

该物品现在有

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); }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们将扩展映射:

HasMany(x => x.Properties)
    .Access.ReadOnlyPropertyThroughCamelCaseField(Prefix.Underscore)
    .Component(c =>
    {
        c.Map(x => x.Key).Column("IDNumber")
        c.Map(x => x.Value).Column("TextField")
    })
    ...
    ;
Run Code Online (Sandbox Code Playgroud)

以及查询,它将按预期工作:

session
    .Query<Item>()
    .Where(r => 
        r.Properties.Any(g => g.Value == "SomeText")
    )
Run Code Online (Sandbox Code Playgroud)

注意:根据我的经验,此解决方法不应该是解决方法。这是首选方式。NHibernate 支持很多功能,但使用对象会带来更多利润