我刚刚开始使用NHibernate。我有两个对象:
public class Supplier
{
public virtual int id{get;set;}
public virtual SupplierAddress address{get;set;}
public virtual string Name{get;set;}
}
public class SupplierAddress
{
public virtual int id{get;set;}
public virtual Supplier{get;set;}
public virtual string SupplierAddressLine{get;set;}
}
当我想创建一个新的Supplier
时,我创建了一个新对象:
var supplierAddress = new SupplierAddress {
SupplierAddressLine = "someLine"
}
var supplier = new Supplier
{
Name = "someName",
SupplierAddress = SupplierAddressLine
}
然后,当我尝试使用保存时:
_session.Save(supplier);
我收到错误:“无法将值NULL插入列'id'
for SupplierAddress
Id(x => x.Id).GeneratedBy.Identity().Column("Id");
References(x => x.Supplier).Column("SupplierId");
Map(x => x.AddressLine1).Column("AddressLine1").Not.Nullable().Length(255);
供应商
Id(x => x.Id).GeneratedBy.Identity().Column("Id");
References(x => x.SupplierAddress).Column("SupplierAddressId").Not.Nullable();
HasMany(x => x.SupplierAddresses).KeyColumn("SupplierId");
答案 0 :(得分:2)
您应该在Supplier
→SupplierAddress
关系中设置一些cascade rules:
References(s => s.SupplierAddress)
.Column("SupplierAddressId")
.Not.Nullable()
.Cascade.All(); /* Cascade operations that happen on `Supplier` */
否则,NHibernate不知道保存父(Supplier
)也应该保存孩子(SupplierAddress
)
修改:我认为您实际上在这里错误地使用了References
。
在映射中,当你说另一个实体References
时,你基本上告诉NHibernate 这段关系的另一面是HasMany
强>
在您的情况下,Supplier
和SupplierAddress
实际上分别没有SupplierAddress
个或Supplier
个。
考虑到这一点,你可能意味着两件事之一:
多个SupplierAddress
共享Suppliers
。这意味着SupplierAddress
实际上有很多 Suppliers
,但Supplier
只有一个SupplierAddress
。
在C#类中,这意味着SupplierAddress
的集合为Suppliers
(或者根本没有引用Supplier
。
在这种情况下,您的数据库表将如下所示:
create table [SupplierAddress]
(
[Id] int identity(1,1) primary key clustered,
[AddressLine1] nvarchar(255) not null
);
create table [Supplier]
(
[Id] int identity(1,1) primary key clustered,
[SupplierAddressId] int not null references [SupplierAddress]([Id])
)
您的C#类看起来像这样:
public class Supplier
{
public virtual int Id { get; set; }
public virtual SupplierAddress SupplierAddress { get; set; }
public virtual string Name { get; set; }
}
public class SupplierAddress
{
public virtual int Id { get; set; }
public virtual string AddressLine1 { get; set; }
}
你的映射看起来像这样:
public class SupplierMap : ClassMap<Supplier>
{
public SupplierMap()
{
Id(s => s.Id).GeneratedBy.Identity().Column("Id");
References(s => s.SupplierAddress)
.Column("SupplierAddressId")
.Cascade.All();
}
}
public class SupplierAddressMap : ClassMap<SupplierAddress>
{
public SupplierAddressMap()
{
Id(s => s.Id).GeneratedBy.Identity().Column("Id");
Map(s => s.AddressLine1)
.Column("AddressLine1")
.Not.Nullable()
.Length(255);
}
}
Supplier
只有一个SupplierAddress
,SupplierAddress
只与一个Supplier
相关联。另一种思考方式是整个SupplierAddress
表可以在逻辑上合并到Supplier
。
在这种情况下,您的数据库表将如下所示:
create table [SupplierAddress]
(
[Id] int identity(1,1) primary key clustered,
[AddressLine1] nvarchar(255) not null,
[SupplierId] int not null
);
create table [Supplier]
(
[Id] int identity(1,1) primary key clustered,
[SupplierAddressId] int references [SupplierAddress]([Id])
);
alter table [SupplierAddress]
add constraint [FK_SupplierAddress_Supplier]
foreign key ([SupplierId]) references [Supplier]([Id])
您的C#类看起来像这样:
public class Supplier
{
private SupplierAddress supplierAddress;
public virtual int Id { get; set; }
public virtual SupplierAddress SupplierAddress
{
get { return this.supplierAddress; }
set
{
this.supplierAddress = value;
this.supplierAddress.Supplier = this;
}
}
public virtual string Name { get; set; }
}
public class SupplierAddress
{
public virtual int Id { get; set; }
public virtual string AddressLine1 { get; set; }
public virtual Supplier Supplier { get; set; }
}
你的映射看起来像这样:
public class SupplierMap : ClassMap<Supplier>
{
public SupplierMap()
{
Id(s => s.Id).GeneratedBy.Identity().Column("Id");
HasOne(s => s.SupplierAddress).PropertyRef(s => s.Supplier)
.Access.CamelCaseField()
.Cascade.All();
}
}
public class SupplierAddressMap : ClassMap<SupplierAddress>
{
public SupplierAddressMap()
{
Id(s => s.Id).GeneratedBy.Identity().Column("Id");
Map(s => s.AddressLine1).Column("AddressLine1");
References(s => s.Supplier).Column("SupplierId").Unique();
}
}
请注意,当Supplier.SupplierAddress
为set
时,地址的Supplier
属性已设置。