4

我有数据库视图 ALL_ATM_DEV_SATTRIB_VALS

DEVICE_ID   ATTRIB_ID    INT_VALUE    STRING_VALUE    DATE_VALUE

1           13           null         10.0.3.50       null
1           14           0            null            null
1           15           null         null            null

2           13           null         10.0.3.51       null
2           14           2            null            null
2           15           null         null            null

实体对象

public class AttributeValue: IAttributeValue
{
    public virtual string StringValue { get; set; }
    public virtual DateTime? DateValue { get; set; }
    public virtual int? IntValue { get; set; }
}

public class Device : IDevice
{
    public virtual long Id { get; set; }        

    public virtual IDictionary<long, IAttributeValue> Values { get; set; }
}

映射文件(hbm)

<class name="Device" table="DEVICES" lazy="true" >

<id name="Id" column="ID" ></id>

<map name="Values " batch-size="10" table="ALL_ATM_DEV_SATTRIB_VALS" lazy="true">
  <key column="DEVICE_ID" />
  <index column="ATTRIB_ID" type="System.Int64" />

  <composite-element class="AttributeValue">
    <property name="StringValue"  column="STRING_VALUE" />
    <property name="DateValue"  column="DATE_VALUE" />
    <property name="IntValue"  column="INT_VALUE" />
  </composite-element>
</map>

</class>

选择字典值可以正常工作,但是当我尝试在 Linq 表达式中使用它时

List<IDevice> a = dc.Get<IDevice>()
                    .Where(x=>x.Values[13].StringValue
                                          .ToLower().Contains("10.0.3"))
                    .ToList();

休眠抛出异常

System.InvalidOperationException: Cannot create element join for a collection of non-entities!

Device我需要的对象中IDictionary。键是 ATTRIB_ID(long),值是AttributeValue

4

1 回答 1

0

Nhibernate 无法创建 sql-query 使用IDictionary<long, IAttributeValue>,因为 IAttributeValue 没有在 hbm 中映射为实体。

但我解决了这个问题。

IDictionary我替换了一到三个更简单的映射:

 <map name="StringValues" table="ALL_ATM_DEV_SATTRIB_VALS" lazy="true" fetch="select">
  <key column="DEVICE_ID" />
  <index column="ATTRIB_ID" type="System.Int64" />
  <element column="STRING_VALUE" type="System.String"/>
</map>
<map name="DateValues" table="ALL_ATM_DEV_SATTRIB_VALS" lazy="true" fetch="select">
  <key column="DEVICE_ID" />
  <index column="ATTRIB_ID" type="System.Int64" />
  <element column="DATE_VALUE" type="System.DateTime"/>
</map>
<map name="IntValues" table="ALL_ATM_DEV_SATTRIB_VALS" lazy="true" fetch="select">
  <key column="DEVICE_ID" />
  <index column="ATTRIB_ID" type="System.Int64" />
  <element column="INT_VALUE" type="System.Int64"/>
</map>

我将此映射仅用于创建结果 sql-query,这就是lazy=true存在的原因,并且永远不会在实体中访问它们IDevice

Data of this maps selected an another sql-query at once, because lazy initialization would cause n+1 sql-queries on DB.

Linq query in my question transformed in :

List<IDevice> a = dc.Get<IDevice>()
                .Where(x=>x.StringValues[13].ToLower().Contains("10.0.3"))
                .ToList();

In IDevice entity defined three maps :

    public virtual IDictionary<long, long> IntValues { get; set; }
    public virtual IDictionary<long, string> StringValues { get; set; }
    public virtual IDictionary<long, DateTime> DateValues { get; set; }
于 2013-02-13T09:02:23.167 回答