我通过一对一的映射看到了一些意外的查询行为,其中" child"记录可能为空。当看起来左连接更合适时,Nhibernate似乎会生成内连接。给出以下架构:
CREATE TABLE [dbo].[Customer](
[CustomerId] [int] IDENTITY(1,1) NOT NULL,
[PersonId] [int] NOT NULL,
[AccountNumber] [int] NOT NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
[CustomerId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Employee](
[EmployeeId] [int] IDENTITY(1,1) NOT NULL,
[PersonId] [int] NOT NULL,
[Title] [varchar](50) NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
(
[EmployeeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Person](
[PersonId] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
[PersonId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [FK_Customer_Person] FOREIGN KEY([PersonId])
REFERENCES [dbo].[Person] ([PersonId])
GO
ALTER TABLE [dbo].[Customer] CHECK CONSTRAINT [FK_Customer_Person]
GO
ALTER TABLE [dbo].[Employee] WITH CHECK ADD CONSTRAINT [FK_Employee_Person] FOREIGN KEY([PersonId])
REFERENCES [dbo].[Person] ([PersonId])
GO
ALTER TABLE [dbo].[Employee] CHECK CONSTRAINT [FK_Employee_Person]
GO
以下课程:
namespace OneToOneMapping.Model
{
public class Person
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Customer Customer { get; set; }
public virtual Employee Employee { get; set; }
}
public class Employee
{
public virtual System.Int32 Id { get; set; }
public virtual Person Person { get; set; }
public virtual string Title { get; set; }
}
public class Customer
{
public virtual System.Int32 Id { get; set; }
public virtual Person Person { get; set; }
public virtual int AccountNumber { get; set; }
}
}
并映射:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="OneToOneMapping"
namespace="OneToOneMapping.Model">
<class name="Person" table="Person" lazy="true" >
<id name="Id" column="PersonId">
<generator class="identity"/>
</id>
<one-to-one name="Customer" cascade="all-delete-orphan" property-ref="Person" class="OneToOneMapping.Model.Customer" />
<one-to-one name="Employee" cascade="all-delete-orphan" property-ref="Person" class="OneToOneMapping.Model.Employee" />
<property name="Name"/>
</class>
<class name="OneToOneMapping.Model.Customer, OneToOneMapping" table="Customer">
<id name="Id" column="CustomerId">
<generator class="identity"/>
</id>
<property name="AccountNumber"/>
<many-to-one name="Person" class="Person" column="PersonId" unique="true" cascade="save-update"/>
</class>
<class name="OneToOneMapping.Model.Employee, OneToOneMapping" table="Employee" lazy="true" mutable="true">
<id name="Id" column="EmployeeId">
<generator class="identity"/>
</id>
<property name="Title"/>
<many-to-one name="Person" class="Person" column="PersonId" unique="true" cascade="save-update"/>
</class>
</hibernate-mapping>
我无法创建linq查询,我可以返回一个投影,指示客户是否也是员工(反之亦然)。运行类似以下语句的内容:
var t = Session.Query<Customer>().Select(c => new { AccountNumber = c.AccountNumber, Name= c.Person.Name, IsEmployee = c.Person.Employee.Id != null }).ToList();
生成以下SQL(请注意&#34;其中&#34;子句可防止任何不具备关联员工记录的客户记录完全退回):
SELECT customer0_.AccountNumber AS col_0_0_
,person1_.NAME AS col_1_0_
,employee2_.EmployeeId AS col_2_0_
FROM Customer customer0_
LEFT JOIN Person person1_ ON customer0_.PersonId = person1_.PersonId
,Employee employee2_
WHERE person1_.PersonId = employee2_.PersonId
我希望它生成如下内容,以便在记录不存在时返回null EmployeeId:
SELECT customer0_.AccountNumber AS col_0_0_
,person1_.NAME AS col_1_0_
,employee2_.EmployeeId AS col_2_0_
FROM Customer customer0_
LEFT JOIN Person person1_ ON customer0_.PersonId = person1_.PersonId
Left Join Employee employee2_ on person1_.PersonId = employee2_.PersonId
我是否遗漏了某些东西,或者这是一个已知的问题,与#34;一对一&#34;映射?
答案 0 :(得分:0)
我们已经在投影中使用子查询确定了一种不同的查询方法。我认为潜在的问题与此处的公开问题有关:https://nhibernate.jira.com/browse/NH-3117?jql=text%20~%20%22one%20to%20one%22。似乎NHibernate linq提供程序没有正确处理引用项可能不存在的一对一映射。
解决方法:
DateTimePicker.Format = DateTimePickerFormat.Custom
DateTimePicker.CustomFormat = "dd-MM-yyyy"
生成以下SQL:
var t = Session.Query<Customer>()
.Select(c => new {
AccountNumber = c.AccountNumber,
Name= c.Person.Name,
IsEmployee = Session.Query<Employee>().Any(e => e.Id == c.Person.Id)
}).ToList();