我正在努力使用Fluent NHibernate整合一个简单的POC应用程序,试图证明它可以完成我们当前的手动数据访问工具的所有功能。我的老板担心的一个边缘案例是能够在一个查询中访问同一数据库中的多个模式。到目前为止,只要查询一次只触及一个模式,我就可以从两个模式中的表中提取数据。如果我尝试执行一个将从两个模式连接表的命令,它就会爆炸。
根据我看到的错误消息,我不认为问题是加入模式,而是因为我需要加入表的两个字段都是非关键字段。这两个表的结构是这样的:
Customer (in schema 1) -------- int CustomerId (Primary Key) string Name ...other fields Order (in schema 2) -------- int OrderId (primary key) string CustomerName ...other fields
直接使用sql我可以加入Name / CustomerName字段并从两个表中获取数据。但是,在尝试从Order表中提取数据并包含Customer表中的数据时,使用NHibernate时,我不断收到“System.FormatException:输入字符串格式不正确”。这让我相信NHibernate正在尝试加入CustomerName字段和CustomerId字段。
我知道如何告诉它在我的订单映射中使用CustomerName字段,但我无法找到告诉加入Customer表的Name字段的方法。
My Mappings看起来像这样:
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是为了得到我想要的结果:
select o.OrderId, o.CustomerName, c.CustomerId
from order o
inner join customer c on c.Name = o.CustomerName
这甚至可能吗? 是否有不同/更好的方法来解决这个问题?
答案 0 :(得分:6)
我没有使用多个模式,但我发现的用于映射非关键字段的方法如下:
在OrderMap中...... 引用(order =&gt; order.Customer).Column(“CustomerName”)。PropertyRef(“Name”);
其中PropertyRef(“Name”)实际上是指Customer类上的Name属性(您将在CustomerMap中定义)。
我刚刚开始使用FNH,所以你可能会找到更好的解决方案,但我希望这会有所帮助。
答案 1 :(得分:1)
我举例说明如何使用注释在Hibernate中映射非关键字段 请将其转换为相应的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`)
)
客户实体
@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;
}
}
订单实体
@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(我删除了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=?
答案 2 :(得分:0)
加入模式没有问题,您只需要在映射中指定模式:
public sealed class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Table("Customer");
Schema("dbo");
// etc.
}
}
您的订单表应将CustomerId作为外键,而不是CustomerName。这是实现一对多关系的标准方法,并不是NHibernate特有的。如果有,那么OrderMap中的映射是:
References(x => x.Customer, "CustomerId");