2009-10-20 7 views
5

Estoy trabajando en la creación de una aplicación POC sencilla utilizando Fluent NHibernate para intentar demostrar que puede hacer todo lo que hace con nuestra herramienta actual de acceso a datos y mucho más. Uno de los casos marginales que preocupa a mi jefe es la posibilidad de acceder a múltiples esquemas dentro de la misma base de datos en una consulta. Hasta ahora he podido extraer datos de las tablas en ambos esquemas siempre que la consulta solo toque un esquema a la vez. Si trato de ejecutar un comando que unirá las tablas de ambos esquemas, explotará.Únase entre dos campos no clave

Basándome en los mensajes de error que estoy viendo, no creo que el problema sea unir esquemas, sino más bien el hecho de que los dos campos en los que necesito unirme a las tablas no son clave campos. La estructura de los dos mesa es algo como esto:

 
Customer (in schema 1) 
-------- 
int CustomerId (Primary Key) 
string Name 
...other fields 

Order (in schema 2) 
-------- 
int OrderId (primary key) 
string CustomerName 
...other fields 

mediante sql directamente me pueda unir en los campos Nombre/CustomerName y obtener los datos de las dos tablas. Sin embargo, al usar NHibernate sigo obteniendo una "System.FormatException: la cadena de entrada no estaba en el formato correcto" al intentar extraer datos de la tabla de pedidos e incluir datos de la tabla de clientes. Esto me lleva a creer que NHibernate está intentando unirse al campo CustomerName y al campo CustomerId.

Sé cómo decirles que utilicen el campo CustomerName en mi asignación de pedidos, pero no puedo encontrar la manera de indicarme que me unan en el campo Nombre de la tabla de clientes.

Mis Asignaciones de ser algo como esto:

public class CustomerMap : ClassMap<Customer> 
{ 
    public CustomerMap() 
    { 
     Id(x => x.Id) 
      .Column("CustomerId"); 
     Map(x => x.Name); 
    } 
} 


public class OrderMap : ClassMap<Order> 
{ 
    public OrderMap() 
    { 
     Schema("schema2"); 
     Id(x => x.Id) 
      .Column("OrderID"); 
     Map(x => x.CustomerName) 
      .Column("CustomerName"); 
     References<Customer>(x => x.Customer, "CustomerName"); 
    } 
} 

El SQL que escribiría para obtener los resultados que quiero sería algo así como:

select o.OrderId, o.CustomerName, c.CustomerId 
from order o 
inner join customer c on c.Name = o.CustomerName 

Es esto posible? ¿Hay alguna manera diferente/mejor de hacer esto?

Respuesta

6

no he trabajado con varios esquemas, pero el enfoque que he encontrado para mapeo de campos no clave es la siguiente:

En OrderMap ... Referencias (orden => order.Customer). Columna ("NombreCliente"). PropertyRef ("Nombre");

Donde PropertyRef ("Nombre") se refiere realmente a la propiedad Name en su clase Customer (que definiría en CustomerMap).

Estoy empezando con FNH, por lo que puede encontrar una mejor solución, pero espero que esto ayude.

+0

Gracias! Eso lo hizo. Intenté tanto 'Column' como 'PropertyRef' individualmente, pero no pensé en probarlos juntos por algún motivo. – Hamman359

+0

Genial, esto es exactamente lo que estaba buscando. También puede beneficiarse de un tipado fuerte con su parámetro PropertyRef mediante el uso de lambdas, es decir, PropertyRef (x => x.Name). Esto significa que no se romperá si refactoriza su clase de Cliente. – nukefusion

+0

¡Eso ayudó incluso con Uno para muchos! :) – Turowicz

0

unirse a través de esquemas no es ningún problema, sólo tiene que especificar el esquema en su asignación:

public sealed class CustomerMap : ClassMap<Customer> 
{ 
    public CustomerMap() 
    { 
     Table("Customer"); 
     Schema("dbo"); 
     // etc. 
    } 
} 

Su tabla de orden debe tener CustomerId como una clave externa, no CustomerName. Esa es la forma estándar de implementar una relación uno a muchos y no es particular de NHibernate. Si usted tiene que, la asignación en OrderMap es:

References(x => x.Customer, "CustomerId"); 
+0

Gracias, pero eso realmente no aborda mi pregunta. Como indiqué, ya sabía cómo hacer referencia a un esquema diferente. Mi problema fue cuando intenté unirme a las dos mesas. Además, aunque acepto que la clave externa debe ser CustomerId y no CustomerName, eso no es posible en este caso, ya que este sistema ya se encuentra en PROD desde hace casi un año y no tengo control sobre el esquema que necesitaría modificar para que esto ocurra. cambio. Dada esa limitación, necesito unirme a los campos de cadenas. La respuesta de David indica el enfoque que pude usar para resolver esto. – Hamman359

1

estoy ejemplo, ¿cómo se puede asignar campos clave NO en Hibernate usando anotación dando.
Por favor, conviértalo en nHibernate correspondiente.

CREATE TABLE `Customer` (
    `CUSTOMER_ID` bigint(20) NOT NULL AUTO_INCREMENT, 
    `NAME` varchar(100) NOT NULL, 
    PRIMARY KEY (`CUSTOMER_ID`) 
) 

CREATE TABLE `Order` (
    `ORDER_ID` bigint(20) NOT NULL AUTO_INCREMENT, 
    `CUSTOMER_NAME` varchar(100) NOT NULL, 
    PRIMARY KEY (`ORDER_ID`) 
) 

entidad de cliente

@Entity 
@Table(name = "CUSTOMER") 
public class Customer{ 

    private long customerId; 
    private String name; 
    private Order order; 


    public Customer() { 
    } 

    public Customer(String name) { 
     this.name= name; 

    } 

    @Id 
    @GeneratedValue 
    @Column(name = "CUSTOMER_ID") 
    public long getCustomerId() { 
     return this.customerId; 
    } 

    public void setCustomerId(long customerId) { 
     this.customerId= customerId; 
    } 

    @Column(name = "NAME", nullable = false, length = 100, insertable=false, updatable=false) 
    public String getName() { 
     return this.name; 
    } 
    public String setName(String name) { 
     return this.name; 
    } 

    @ManyToOne 
    @JoinColumn(name = "NAME", referencedColumnName = "CUSTOMER_NAME") 
    public Order getOrder() { 
     return order; 
    } 


    public void setOrder(Order order) { 
     this.order= order; 
    } 


} 

Solicitar Entidad

@Entity 
@Table(name = "ORDER") 
public class Order implements Serializable { 

    private long orderId; 
    private String customerName; 

    public Ortder() { 
    } 

    public Order(String customerName) { 
     this.customerName= customerName; 

    } 

    @Id 
    @GeneratedValue 
    @Column(name = "ORDER_ID") 
    public long getOrderId() { 
     return this.orderId; 
    } 

    public void setOrderId(long orderId) { 
     this.orderId= orderId; 
    } 

    @Column(name = "CUSTOMER_NAME", nullable = false, length=250) 
    public String getCustomerName() { 
     return this.customerName; 
    } 

    public void setCustomerName(String customerName) { 
     this.customerName= customerName; 
    } 


} 

Customer customer = new Customer("C1"); 
session.load(customer , 5L);  
System.out.println(customer.getName()); 
Order order = customer.getOrder(); 
System.out.println(order.getCustomerName()); 

SQL se generan d me gusta (he eliminado el alias generado por Hibernate)

select customer.CUSTOMER_ID, customer.NAME, order.ORDER_ID, 
order.CUSTOMER_NAME 
from CUSTOMER 
left outer join ORDER **on NAME=CUSTOMER_NAME** where CUSTOMER_ID=? 
Cuestiones relacionadas