2012-11-19 18 views
4

我有DB视图ALL_ATM_DEV_SATTRIB_VALSNhibernate的地图复合元件

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> 

选择二ctionaries值正常工作,但是当我试图Linq中使用表达式

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

NHibernate的抛出异常

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

在我需要有IDictionary对象Device。键是ATTRIB_ID(长),值为AttributeValue

+0

它是相同的,如果你放弃了我,所以字典是'的IDictionary <长,AttributeValue>'另外,'name =“Values”'不应该有尾随空格,尽管我不认为这是问题。 – weston

+0

您示例代码中的“dc”是什么类型? 'IQueryable'?我认为问题在于,您在LINQ查询中使用了'IDevice'。异常消息告诉我你应该使用在'Device'的.hbm文件中定义的类型。那样有用吗?我没有可用的IDE来确认,因此我首先将它作为评论发布。 –

回答

1

Nhibernate无法创建使用IDictionary<long, IAttributeValue>的sql查询,因为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查询,这就是为什么lazy=true存在,并且 从未访问他们在实体IDevice

此映射的数据一次选择另一个sql-query,因为懒惰初始化会导致数据库上的n + 1个sql查询。

Linq查询我的问题在转化:

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

IDevice实体定义三张地图:

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