2009-10-20 4 views
5

Pracuję nad połączeniem prostej aplikacji POC przy użyciu Fluent NHibernate, aby spróbować pokazać, że może ona zrobić wszystko, co jest obecnie w naszym ręcznym narzędziu dostępu do danych i wiele więcej. Jednym z niepokojących przypadków, o które martwi się mój szef, jest możliwość dostępu do wielu schematów w tej samej bazie danych w jednym zapytaniu. Do tej pory byłem w stanie pobierać dane z tabel w obu schematach, o ile zapytanie dotyka tylko jednego schematu naraz. Jeśli spróbuję wykonać polecenie, które będzie łączyć tabele z obu schematów, to rozwinie się.Łączenie dwóch nie-kluczowych pól

Na podstawie komunikatów o błędach, które widzę, nie uważam, że problem polega na łączeniu się schematów, ale raczej z tym, że dwa pola, które muszę dołączyć do tabel są niezwiązane z kluczem pola. Struktura dwóch tabeli jest mniej więcej tak:

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

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

pomocą SQL bezpośrednio mogę dołączyć na nazwę/pól CustomerName i uzyskać dane z obu tabel. Jednak przy użyciu NHibernate nadal otrzymuję "System.FormatException: wejściowy ciąg nie był w poprawnym formacie" podczas próby pobrania danych z tabeli zamówień i uwzględnienia danych z tabeli klienta. To prowadzi mnie do przekonania, że ​​NHibernate próbuje dołączyć do pola CustomerName i pola CustomerId.

Wiem, jak polecić mu użycie pola CustomerName w moim mapowaniu zamówienia, ale nie mogę wymyślić sposobu, aby powiedzieć, aby dołączyć do pola Nazwa w tabeli klienta.

Moi Mappings wyglądać następująco:

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

SQL Chciałbym napisać, aby otrzymać wyniki chcę byłoby coś jak:

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

Czy to w ogóle możliwe? Czy istnieje inny/lepszy sposób na zrobienie tego?

Odpowiedz

6

nie mam pracy z wieloma schematami, ale podejście Znalazłem dla mapowania pól non-klucz jest w następujący sposób:

W OrderMap ... Referencje (kolejność => order.Customer). Column ("CustomerName"). PropertyRef ("Name");

Gdzie PropertyRef ("Nazwa") faktycznie odwołuje się do właściwości Nazwa w klasie Klienta (którą zdefiniowałbyś w Mapie Klienta).

Po prostu zaczynam od FNH, więc możesz znaleźć lepsze rozwiązanie, ale mam nadzieję, że to pomaga.

+0

Dzięki! Tak było. Próbowałem pojedynczo "Kolumny" i "PropertyRef", ale nie sądziłem, że spróbuję ich razem z jakiegoś powodu. – Hamman359

+0

Świetnie, właśnie tego szukałem. Możesz również skorzystać z silnego pisania za pomocą parametru PropertyRef, używając zamiast niego lambdas, tj. PropertyRef (x => x.Name). Oznacza to, że nie złamie się, jeśli zmienisz swoją klasę klienta. – nukefusion

+0

To pomogło nawet z Jednym do wielu! :) – Turowicz

0

Dołączenie całej schematów nie jest problemem, wystarczy podać schemat w swoim mapowania:

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

Twój stół zamówienie powinno mieć customerId jako klucz obcy, a nie CustomerName. Jest to standardowy sposób implementacji relacji jeden do wielu i nie ma on wpływu na NHibernate. Jeśli masz, że odwzorowanie w OrderMap jest:

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

Dzięki, ale to nie rozwiązuje mojego pytania. Jak już wskazałem, już wiedziałem, jak odwołać się do innego schematu. Mój problem polegał na tym, że próbowałem dołączyć do dwóch stołów. Ponadto, podczas gdy zgadzam się, że klucz obcy powinien być CustomerId, a nie CustomerName, nie jest to możliwe w tym przypadku, ponieważ system ten jest już w PROD przez prawie rok i nie mam żadnej kontroli nad schematem, który musiałby zostać zmodyfikowany, aby uczynić to zmiana. Biorąc pod uwagę to ograniczenie, muszę dołączyć do pól łańcuchowych. Odpowiedź Dawida wskazuje na podejście, którego mogłem użyć, aby rozwiązać ten problem. – Hamman359

1

daję przykład w jaki sposób można mapować pól kluczowych NON w Hibernate używając adnotacji.
Konwersja na odpowiednią nHibernate.

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

Podmiot klienta

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


} 

Zamówienie Podmiot

@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 będzie generować d (usunąłem alias wygenerowany przez 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=?