2009-04-01 9 views
9

Estoy seguro de que esto es una cuestión sencilla, pero considere lo siguiente: tengo una referencia entre la empresa y el sector de la siguiente manera:Fluido NHibernate - Cómo direccionar la columna de clave externa como una propiedad

public class Company { 
    public Guid ID { get; set; } 
    public Sector Sector { get; set; } 
    public Guid SectorID { get; set; } 
} 

public class Sector { 
    public Guid ID { get; set; } 
    public string Name { get; set; } 
} 

Ok. Lo que quiero es que el SectorID del objeto de la empresa se rellene después de que me vaya:

(new Company()).Sector = new Sector() { Name="asdf" } 

y hacer un color.

La asignación que estoy utilizando amablemente crea una columna adicional en la base de datos denominada Id_Sector en la tabla Compañía, pero no está disponible como una propiedad en la Empresa. Quiero que se llene la propiedad del SectorID.

El mapeo Actualmente estoy usando en el CompanyMap es

References(c => c.Sector).Cascade.All(); 

¿Alguien tiene alguna idea?


Gracias por su respuesta. Lamentablemente si hago la segunda opción (ajuste el nombre de la columna de la columna para que sea la misma que la propiedad, o conjunto Map(x => x.SectorID, "Sector_Id") entonces consigo el error:

System.IndexOutOfRangeException: índice inválido 7 para este SqlParameterCollection con Count = 7.

Es posible que tenga que hacer la primera opción, pero me preocupa que se active una consulta adicional cuando llame al SectorID, ya que saca al Sector del DB (a menos que esté ansioso de cargarse, que es un poco molesto).

Me sorprende que no haya una respuesta fácil a esto.


¡WOW! Si uso

public virtual Guid SectorID 
{ 
    get { return Sector.ID; 
} 

continuación nhibernate es lo suficientemente inteligente como para saber que la columna Sector_id en la consulta organización es en realidad lo mismo que Sector.ID y devuelve esto bajo las capuchas. No envía una consulta adicional, incluso si la carga es lenta. ¡Estoy impresionado!


Como seguimiento ... Parece que hibernación no está realmente escrito para ser capaz de asignar la columna de clave externa de los objetos. Aunque esto puede ser un poco molesto para los servidores web, tiene sentido ya que se trata de una preocupación de persistencia que no es realmente una preocupación objetiva. Estoy utilizando asp.net MVC y he escrito una carpeta de modelo personalizada que tomará una caja de entrada de contacto de nombre (en lugar de ContactID), nuevo un nuevo contacto con la ID de lo que está en la caja de tex, y luego aplicar esto a la propiedad del Modelo. Esto evita el problema con listas desplegables en interfaces web. Publicará el código si alguien está interesado.

Respuesta

2

Dos pensamientos: Antes que nada, ¿algo así no podría lograr lo que quieres?

public class Company { 
    public Guid ID { get; set; } 
    public Sector Sector { get; set; } 
    public Guid SectorID { 
     get { return Section.ID; } 
     // Really not sure what behavior your setter should have here; Maybe it shouldn't even have one? 
     set { Sector = new Sector { ID = value }; } 
    } 
} 

En segundo lugar, cuando se dice que el mapeo crea una columna en el PP llama Sector_Id, es que además de una columna que creó nombrado SectorID?De ser así, puede cambiar el nombre de la columna para que use el nombre correcto (here's the documentation for mappings, consulte algunos encabezados abajo "Especificación del nombre de la columna").

Además, ¿está mapeando la propiedad SectorID (por ejemplo, "Mapa (x => x.SectorID," Sector_Id ")")?

2

Steve no necesita la propiedad ForeignKey en la clase POCO.

Por ejemplo, si intenta obtener la identificación del autor del artículo, no se realizará la selección de unión.

var authorID = Article.Author.ID

13

Esto se hace fácilmente con una fórmula propiedad.

public class Company { 
    public virtual Guid Id { get; set; } 
    public virtual Guid? SectorId { get; set; } 
    public virtual Sector Sector { get; set; } 
} 

public class CompanyMap : ClassMap<Company> { 
    public CompanyMap() { 
    Id(x => x.Id); // Maps to a column named "Id" 
    References(x => x.Sector); // Maps to a column named "Sector_id", unless you change the NHibernate default mapping rules. 
    Map(x => x.SectorId).Formula("[Sector_id]"); 
    }  
} 

Esto debería actuar exactamente como desee. Cuando el Company es nuevo, SectorId será nulo; cuando se obtiene Company de la base de datos, SectorId se completará con el valor de la fórmula dada. El SectorId está expuesto como una propiedad, lo que lo hace realmente agradable para lidiar con los menús desplegables de la web, etc. Cuando guarde, aún necesitará vincular la asociación "real". Suponiendo que SectorId fue seleccionado en una forma ...

using (var txn = session.BeginTransaction()) { 
    // Set the FK reference. 
    company.Sector = session.Load<Sector>(company.SectorId); 
    // Save the new record. 
    session.Save(company); 
    // Commit the transaction. 
    txn.Commit(); 
} 
+0

te doy puntos para resolver el error que estaba recibiendo, pero esto parece completamente no intuitiva. Parece que NHibernate tiene un problema de diseño si no puede manejar un escenario tan común como tener tanto el ID de FK como la instancia de objeto asociada como propiedades. –

Cuestiones relacionadas