我有两张桌子,
SQL
CREATE TABLE [dbo].[WidgetProperty](
[WidgetPropertyID] [int] IDENTITY(1,1) NOT NULL,
[WidgetID] [int] NOT NULL,
[PropertyID] [int] NOT NULL,
[PropertyIndex] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[WidgetPropertyID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[WidgetProperty] ADD DEFAULT ((1)) FOR [PropertyIndex]
HBM
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Nt.Engine.domain.WidgetProperty,Nt.Engine" table="WidgetProperty" lazy="true">
<id name="WidgetPropertyID" column="WidgetPropertyID">
<generator class="native" />
</id>
<property name="WidgetID" column="WidgetID" type="Int32" not-null="true" />
<property name="PropertyID" column="PropertyID" type="Int32" not-null="true" />
<property name="PropertyIndex" column="PropertyIndex" type="Int32" not-null="true" />
<one-to-one name="PropertyDetail" cascade="all" foreign-key="none" class="Nt.Engine.domain.PropertyDetail,Nt.Engine" />
</class>
</hibernate-mapping>
MODEL
public class WidgetProperty
{
public virtual Int32 WidgetPropertyID { get; set; }
public virtual Int32 WidgetID { get; set; }
public virtual Int32 PropertyID { get; set; }
public virtual Int32 PropertyIndex { get; set; }
public virtual PropertyDetail PropertyDetail { get; set; }
}
SQL
CREATE TABLE [dbo].[PropertyDetail](
[PropertyID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[Length] [nvarchar](50) NOT NULL,
[Type] [smallint] NOT NULL,
[DefaultHtml] [nvarchar](600) NULL,
CONSTRAINT [PK_PropertyDetail] PRIMARY KEY CLUSTERED
(
[PropertyID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[PropertyDetail] ADD CONSTRAINT [DF__tblProper__Prope__276EDEB3] DEFAULT ((1)) FOR [Type]
HBM
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Nt.Engine.domain.PropertyDetail,Nt.Engine" table="PropertyDetail" lazy="true">
<id name="PropertyID" column="PropertyID">
<generator class="native" />
</id>
<property name="Name" column="Name" type="string" length="50" not-null="true" />
<property name="Length" column="Length" type="string" length="50" not-null="true" />
<property name="Type" column="Type" type="byte" not-null="true" />
<property name="DefaultHtml" column="DefaultHtml" type="string" length="600" not-null="false" />
</class>
</hibernate-mapping>
MODEL
public class PropertyDetail
{
public virtual Int32 PropertyID { get; set; }
public virtual String Name { get; set; }
public virtual String Length { get; set; }
public virtual byte Type { get; set; }
public virtual String DefaultHtml { get; set; }
}
基本上在第一个表中,每个WidgetID
都有几行,PropertyID
一对一地引用PropertyDetail
表,因此每个WidgetProperty.PropertyID在PropertyDetail
表中只有一行。
在管理器中,如果我通过widgetID
(es:4)调用对象,则WidgetProperty.PropertyDetail
始终为null。任何提示?
答案 0 :(得分:1)
一对一引用用于连接共享相同PK的记录,或者辅助表具有引用父行的FK。 (使用property-ref选项)在您的情况下,您希望父表上的列指向子行。这被配置为多对一关系。
<many-to-one name="PropertyDetail" cascade="all" column="PropertyId" class="Nt.Engine.domain.PropertyDetail,Nt.Engine" />
如果你想要一对一,那么你需要用一个WidgetPropertyId替换PropertyDetail表上的PropertyId。基本上如果PropertyId值等于WidgetPropertyId,那么你实际上会使用当前代码返回一行,这肯定不是你期望的那样。即如果你有一个WidgetProperty / w ID 1234和一个PropertyId为5, if 有一个ID为1234的PropertyDetail它将返回与Widget 1234关联,因为一对一的性质寻找匹配的PK。
编辑:上面做了一个修正。如果你想要一对一,你可以反转FK关联,在你的情况下添加一个WidgetPropertyId到你的PropertyDetail并从WidgetProperty中删除PropertyId。从那里你可以设置从Widget到PropertyDetail的一对一,就像你移除外键并用property-ref替换它来告诉NH通过它的FK列链接PropertyDetail而不是PK:
<one-to-one name="PropertyDetail" cascade="all" property-ref="WidgetPropertyId" class="Nt.Engine.domain.PropertyDetail,Nt.Engine" />