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

时间:2013-12-29 20:04:19

标签: nhibernate fluent-nhibernate linq-to-nhibernate nhibernate-criteria

我需要一种方法来在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相似但不相同

1 个答案:

答案 0 :(得分:3)

处理IDictionary<TValueType, TValueType>通常会带来更多问题而不是优势。一种方法解决方法,是引入一个新对象(我称之为MyWrapper),其属性为KeyValue (只是一个例子命名)

这样我们必须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可带来更多利润