Nhibernate Map component

I have a DB view 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 

Object Objects

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

Mapping file (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> 

Choosing dictionary values works correctly, but when I tried to use it in Linq expressions

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

nhibernate exception exception

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

In the Device object, I need to have an IDictionary . The key is ATTRIB_ID (long), the value is AttributeValue

+4
source share
1 answer

Nhibernate cannot use the sql query IDictionary<long, IAttributeValue> because IAttributeValue does not appear in hbm as an entity.

But I solved this problem.

I replaced the display of one IDictionary with three simpler ones:

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

I use these cards only to create a sql query for the result , so lazy=true present, and never access them in the IDevice

The data from these maps immediately chose another sql query, because lazy initialization will cause n + 1 sql-query in the database.

The Linq query in my question is converted to:

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

Three maps are defined in an IDevice entity:

  public virtual IDictionary<long, long> IntValues { get; set; } public virtual IDictionary<long, string> StringValues { get; set; } public virtual IDictionary<long, DateTime> DateValues { get; set; } 
+1
source

Source: https://habr.com/ru/post/1446981/


All Articles