使用流畅的nhibernate映射实体oneToMany

问题似乎很简单但是我在尝试映射这些实体时遇到了很多麻烦。 我只是看不出我做错了什么。 你们能帮助我吗?

我有课堂Cliente

 public class Cliente { public Cliente () { } public virtual int ClienteId { get; set; } public IList ListaMedidores { get; set; } public virtual string NumeroMedidor { get; set; } } 

并且上课Medidor

 public class Medidor { public Medidor() { } public virtual string NumeroMedidor { get; set; } public virtual string MarcaMedidor { get; set; } public virtual Cliente Cliente { get; set; } } 

我试着像这样映射

 public ClienteMap() { Map(x => x.NumeroMedidor).Column("CORE_NUMERO_MEDIDOR"); HasMany(x => x.ListaMedidores) .KeyColumn("NUMERO_MEDIDOR").Inverse().Cascade.All(); } public MedidorMap() { Table("medidor"); LazyLoad(); Id(x => x.NumeroMedidor).Column("NUMERO_MEDIDOR"); Map(x => x.TipoMedidor).Column("TIPO_MEDIDOR"); References(x => x.Cliente).Column("CORE_NUMERO_MEDIDOR"); } 

目标是根据数据库提供我的Medidor列表。 所以我做了:

 Session.Query().Fetch(x => x.ListaMedidores).ToList(); 

而且我的列表总是空着的。 即使有这些表格的数据……我将不胜感激任何forms的帮助或建议。

问候

编辑

我的数据库是这样的:


 CREATE TABLE CLIENTE
 (
   CORE_ID NUMBER NOT NULL,
   CORE_NUMERO_MEDIDOR VARCHAR2(50 BYTE)
 )

 CREATE TABLE MEDIDOR
 (
   NUMERO_MEDIDOR VARCHAR2(50 BYTE),
   MARCA_MEDIDOR VARCHAR2(50 BYTE)
 )

鉴于sql select * from cliente where core_numero_medidor = '3569371'

 CORE_ID CORE_NUMERO_MEDIDOR 123 3569371 

select * from MEDIDOR where numero_medidor = '3569371'的sql select * from MEDIDOR where numero_medidor = '3569371'

 NUMERO_MEDIDOR MARCA_MEDIDOR 3569371 general_motors 3569371 kia 3569371 FIAT 

所以我想在IList Lista Medidores上的IList Lista Medidores上获得3个元素。

编辑

我改为:

 public class Cliente { public Cliente () { } public virtual int ClienteId { get; set; } public IList ListaMedidores { get; set; } public virtual string NumeroMedidor { get; set; } } public class Medidor { public Medidor() { } public virtual string NumeroMedidor { get; set; } public virtual string MarcaMedidor { get; set; } } 

并将ClienteMap地图ClienteMap为:

 Map(x => x.NumeroMedidor).Column("NUMERO_MEDIDOR"); HasMany(x => x.ListaMedid) .KeyColumns.Add("NUMERO_MEDIDOR") .Table("MEDID") .PropertyRef("CoreNumeroCliente") .Cascade.All(); 

现在列表获得了预期的记录数,但所有记录都与第一个记录相同。 即:

预期

 NUMERO_MEDIDOR MARCA_MEDIDOR 3569371 general_motors 3569371 kia 3569371 FIAT 

我的结果

 NUMERO_MEDIDOR MARCA_MEDIDOR 3569371 general_motors 3569371 general_motors 3569371 general_motors 

有什么建议? 到目前为止,我要感谢@RadimKöhler的帮助。

另一个编辑

我找到了解决方案!

我试图将非唯一列映射为主键…我只是将列更改为真正的主键并且工作正常!

所以现在这是解决方案

 public class Cliente { public Cliente () { } public virtual int ClienteId { get; set; } public IList ListaMedidores { get; set; } public virtual string NumeroMedidor { get; set; } } public class Medidor { public Medidor() { } public virtual string NumeroMedidor { get; set; } public virtual string MarcaMedidor { get; set; } } public class ClienteMap : ClassMap { public ClienteMap() { Map(x => x.NumeroMedidor).Column("NUMERO_MEDIDOR"); HasMany(x => x.ListaMedid) .KeyColumns.Add("NUMERO_MEDIDOR") .Table("MEDID") .PropertyRef("CoreNumeroCliente") .Cascade.All(); } } public class MedidorMap : ClassMap { public MedidorMap() { LazyLoad(); Id(x => x.NumeroMedidor).Column("NUMERO_MEDIDOR"); Map(x => x.MarcaMedidor).Column("MARCA_MEDIDOR"); [...] //Other properties } } 

这是我的查询:

 Session.Query() .Fetch(x => x.ListaMedid) 

我真的很感谢RadimKöhler的帮助。 他的耐心,关注和帮助解决问题的意愿使我缺乏感谢的方式……我只能祝他生活中一切顺利。

我真的希望这个主题可以帮助有同样问题的人。

问候。

毕竟,使用这些SQL脚本(在我的情况下调整SQL Server)

 CREATE TABLE CLIENTE ( CORE_ID int NOT NULL, CORE_NUMERO_MEDIDOR VARCHAR(50) ) CREATE TABLE MEDIDOR ( NUMERO_MEDIDOR VARCHAR(50), MARCA_MEDIDOR VARCHAR(50) ) 

使用这些实体(所有属性都是虚拟的)

 public class Cliente { public virtual int ClienteId { get; set; } public virtual IList ListaMedidores { get; set; } public virtual string NumeroMedidor { get; set; } } public class Medidor { public virtual string NumeroMedidor { get; set; } public virtual string MarcaMedidor { get; set; } public virtual Cliente Cliente { get; set; } } 

并且只有这一个映射到位:

 public class ClienteMap: ClassMap { public ClienteMap() { Table("CLIENTE"); Id(x => x.ClienteId, "CORE_ID"); Map(x => x.NumeroMedidor).Column("CORE_NUMERO_MEDIDOR"); HasMany(x => x.ListaMedidores) .KeyColumn("NUMERO_MEDIDOR") .Component(com => { com.ParentReference(y => y.Cliente); com.Map(y => y.MarcaMedidor, "MARCA_MEDIDOR"); }) .PropertyRef("NumeroMedidor") .Table("MEDIDOR") // .Inverse() // NO INVERSE, won't work .Cascade.All(); } } 

我可以确认,这个查询将起作用:

 var list = session.Query().Fetch(x => x.ListaMedidores).ToList(); var firt = list.First().ListaMedidores.First(); var last = list.First().ListaMedidores.Last(); Assert.IsTrue(firt.MarcaMedidor != last.MarcaMedidor); 

顺便说一句,这将是(我的首选)生成的xml映射:

                     

有关文档,请参阅

7.2。 依赖对象的集合

one-to-manymany-to-one总是由一列相关联。 这是这样的列,其中包含对另一个表/实体的引用ID(外键)。

在我们的例子中,它必须是Medidor表中的Medidor ,其名称将是"CORE_NUMERO_MEDIDOR" 。 映射应该如下所示

 public ClienteMap() { ... HasMany(x => x.ListaMedidores) //.KeyColumn("NUMERO_MEDIDOR") .KeyColumn("CORE_NUMERO_MEDIDOR") // column in other table .Inverse().Cascade.All(); } public MedidorMap() { ... References(x => x.Cliente) .Column("CORE_NUMERO_MEDIDOR"); // column in this table } 

延伸

基于扩展问题,我们可以看到这种表结构

 CREATE TABLE CLIENTE ( CORE_ID NUMBER NOT NULL, CORE_NUMERO_MEDIDOR VARCHAR2(50 BYTE) ) CREATE TABLE MEDIDOR ( NUMERO_MEDIDOR VARCHAR2(50 BYTE), MARCA_MEDIDOR VARCHAR2(50 BYTE) ) 

数据库引用与C#不同。 似乎,好像

table CLIENTE只引用一个 MEDIDOR,而MEDIDOR只有一个 CLIENTE。

似乎对象应该如下所示:

 public class Cliente { ... //public IList ListaMedidores { get; set; } //public Medidor Medidor { get; set; } } public class Medidor { ... //public virtual Cliente Cliente { get; set; } public virtual IList Clientes { get; set; } } 

并且映射应该是

 public ClienteMap() { ... References(x => x.Medidor, "CORE_NUMERO_MEDIDOR"); } public MedidorMap() { ... Id(x => x.NumeroMedidor).Column("NUMERO_MEDIDOR") // column in this table to be compared HasMany(x => x.Clientes) .KeyColumn("CORE_NUMERO_MEDIDOR") // with column in other table .Inverse().Cascade.All(); } 

另一个扩展

因为第二个表MEDIDOR没有自己的主键(列NUMERO_MEDIDOR),但它可能包含许多相同的值…来自CLIENT TABLE …我们应该使用组件映射

 public ClienteMap() { ... Map(x => x.NumeroMedidor).Column("CORE_NUMERO_MEDIDOR"); HasMany(x => x.ListaMedidores) .Component(com => { com.Parent(y => y.Cliente, "NUMERO_MEDIDOR") .PropertyRef("NumeroMedidor") ; com.Map(y => y.MarcaMedidor, "MARCA_MEDIDOR"); }) .PropertyRef("NumeroMedidor") .Table("MEDIDOR") // .Inverse() // NO INVERSE, won't work .Cascade.All(); }