4

DB ビュー 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

IDictionary<long, IAttributeValue>IAttributeValue がエンティティとして hbm にマップされないため、Nhibernate はSQL クエリの使用を作成できません。

しかし、私はこの問題を解決しました。

1IDictionary対 3 のマッピングをより単純に置き換えました。

 <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>

私はこのマップを create result sql-queryにのみ使用します。それが存在する理由lazy=trueであり、エンティティでそれらにアクセスすることはありませんIDevice

このマップのデータは、すぐに別の SQL クエリを選択しました。これは、遅延初期化により DB で n+1 の SQL クエリが発生するためです。

私の質問のLinqクエリは次のように変換されました:

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

エンティティで定義された3IDeviceつのマップ:

    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 に答える