Nhibernate 一对多关系错误
Nhibernate one to many relationship error
我在 nhibernate 中保存父子关系的子记录时遇到外键错误。我正在使用 Mysql 作为数据库。
插入的外键列的值为“0”
Table
CREATE TABLE Company(
Id INT NOT NULL AUTO_INCREMENT,
Name Varchar(100) NOT NULL,
PRIMARY KEY (Id)
);
CREATE TABLE Client(
ClientId INT NOT NULL AUTO_INCREMENT,
CompanyId INT NOT NULL,
Name Varchar(100) NOT NULL,
PRIMARY KEY (ClientId),
FOREIGN KEY(CompanyId) REFERENCES Company(Id)
);
Class:
public class Company
{
private IList<Client> clients = new List<Client>();
public virtual IList<Client> Clients
{
get { return clients; }
set { clients = value; }
}
public virtual void AddClientToCompany(Client client)
{
client.Company = this;
clients.Add(client);
}
public virtual Company Company { get; set; }
public virtual string Name { get; set; }
public virtual int Id { get; set; }
}
public class Client
{
public virtual Company Company { get; set; }
public virtual string Name { get; set; }
public virtual int CompanyId { get; set; }
public virtual int ClientId { get; set; }
}
Company.hbm.xml
<class name="ConsoleApplication1.Company, ConsoleApplication1" table="Company">
<id name="Id" column="Id" type="int">
<generator class="native"></generator>
</id>
<property name="Name" column="Name" type="String"></property>
<bag name="Clients" table="Client" lazy="false" cascade="all" inverse="true">
<key column="CompanyId"></key>
<one-to-many class="ConsoleApplication1.Client, ConsoleApplication1" />
</bag>
</class>
Client.hbm.xml
<class name="ConsoleApplication1.Client, ConsoleApplication1" table="Client">
<id name="ClientId" column="ClientId" type="int">
<generator class="native"></generator>
</id>
<property name="Name" column="Name" type="String"></property>
<property name="CompanyId" column="CompanyId" type="int" ></property>
<many-to-one name="Company" class="ConsoleApplication1.Company, ConsoleApplication1"
column="CompanyId" cascade="none" insert="false"/>
</class>
Sql 生成:
NHibernate: INSERT INTO Company (Name) VALUES (?p0);?p0 = 'Test Company' [Type:
String (12)]
NHibernate: SELECT LAST_INSERT_ID()
NHibernate: INSERT INTO Client (Name, CompanyId) VALUES (?p0, ?p1);?p0 = 'Test Client' [Type: String (11)], ?p1 = 0 [Type: Int32 (0)]
运行时代码:
Company company = new Company();
company.Name = "Test Company";
Client client = new Client();
client.Name = "Test Client";
company.AddClientToCompany(client);
session.Save(company);
任何想法可能是什么问题?
这里的重点是对于many-to-one
和one-to-many
我们必须使用相同的列"CompanyId"
Company.hbm.xml
<bag name="Clients" table="Client" lazy="false"
cascade="all" inverse="true" >
<!-- wrong column name, it must be parent reference in a child table -->
<!-- <key column="ClientId"></key> -->
<key column="CompanyId" />
<one-to-many class="ConsoleApplication1.Client, ConsoleApplication1" />
</bag>
Client.hbm.xml
- 同一列用于反向映射CompanyId
<many-to-one name="Company"
class="ConsoleApplication1.Company, ConsoleApplication1"
column="CompanyId"
cascade="none"/>
真的,只有一个列 (CompanyId) 负责映射的两边...与数据库中的关系具有相同的主体
延长:
一旦我们更正了映射,我们必须确定我们确实在 C# 中设置了关系的两边。这是必需的,因为 inverse="true"
映射。
最好的方法是扩展 AddClientToCompany()
以分配双方:
public class Company
{
...
public virtual void AddClientToCompany(Client client)
{
clients.Add(client);
// essential line
client.Company = this;
}
...
和运行时代码:
var client = new Client
{
...
}
var company = new Company
{
...
}
// no company knows about client
// and client knows abtou company
company.AddClientToCompany(client);
session.Save(company);
NHibernate 现在将正确地注入具有相关实体 ID 的 INSERT...
毕竟,我们必须真正确定的是,参考映射是可编辑的 - 而不是 属性:
<property name="CompanyId" column="CompanyId" type="int"
insert="false" update="false" >
// the above must be insert and update false
// the below must be editable - it is a reference - managed by NHibernate
<many-to-one name="Company"
class="ConsoleApplication1.Company, ConsoleApplication1"
column="CompanyId" cascade="none"/>
我在 nhibernate 中保存父子关系的子记录时遇到外键错误。我正在使用 Mysql 作为数据库。 插入的外键列的值为“0”
Table
CREATE TABLE Company(
Id INT NOT NULL AUTO_INCREMENT,
Name Varchar(100) NOT NULL,
PRIMARY KEY (Id)
);
CREATE TABLE Client(
ClientId INT NOT NULL AUTO_INCREMENT,
CompanyId INT NOT NULL,
Name Varchar(100) NOT NULL,
PRIMARY KEY (ClientId),
FOREIGN KEY(CompanyId) REFERENCES Company(Id)
);
Class:
public class Company
{
private IList<Client> clients = new List<Client>();
public virtual IList<Client> Clients
{
get { return clients; }
set { clients = value; }
}
public virtual void AddClientToCompany(Client client)
{
client.Company = this;
clients.Add(client);
}
public virtual Company Company { get; set; }
public virtual string Name { get; set; }
public virtual int Id { get; set; }
}
public class Client
{
public virtual Company Company { get; set; }
public virtual string Name { get; set; }
public virtual int CompanyId { get; set; }
public virtual int ClientId { get; set; }
}
Company.hbm.xml
<class name="ConsoleApplication1.Company, ConsoleApplication1" table="Company">
<id name="Id" column="Id" type="int">
<generator class="native"></generator>
</id>
<property name="Name" column="Name" type="String"></property>
<bag name="Clients" table="Client" lazy="false" cascade="all" inverse="true">
<key column="CompanyId"></key>
<one-to-many class="ConsoleApplication1.Client, ConsoleApplication1" />
</bag>
</class>
Client.hbm.xml
<class name="ConsoleApplication1.Client, ConsoleApplication1" table="Client">
<id name="ClientId" column="ClientId" type="int">
<generator class="native"></generator>
</id>
<property name="Name" column="Name" type="String"></property>
<property name="CompanyId" column="CompanyId" type="int" ></property>
<many-to-one name="Company" class="ConsoleApplication1.Company, ConsoleApplication1"
column="CompanyId" cascade="none" insert="false"/>
</class>
Sql 生成:
NHibernate: INSERT INTO Company (Name) VALUES (?p0);?p0 = 'Test Company' [Type: String (12)] NHibernate: SELECT LAST_INSERT_ID()
NHibernate: INSERT INTO Client (Name, CompanyId) VALUES (?p0, ?p1);?p0 = 'Test Client' [Type: String (11)], ?p1 = 0 [Type: Int32 (0)]
运行时代码:
Company company = new Company();
company.Name = "Test Company";
Client client = new Client();
client.Name = "Test Client";
company.AddClientToCompany(client);
session.Save(company);
任何想法可能是什么问题?
这里的重点是对于many-to-one
和one-to-many
我们必须使用相同的列"CompanyId"
Company.hbm.xml
<bag name="Clients" table="Client" lazy="false"
cascade="all" inverse="true" >
<!-- wrong column name, it must be parent reference in a child table -->
<!-- <key column="ClientId"></key> -->
<key column="CompanyId" />
<one-to-many class="ConsoleApplication1.Client, ConsoleApplication1" />
</bag>
Client.hbm.xml
- 同一列用于反向映射CompanyId
<many-to-one name="Company"
class="ConsoleApplication1.Company, ConsoleApplication1"
column="CompanyId"
cascade="none"/>
真的,只有一个列 (CompanyId) 负责映射的两边...与数据库中的关系具有相同的主体
延长:
一旦我们更正了映射,我们必须确定我们确实在 C# 中设置了关系的两边。这是必需的,因为 inverse="true"
映射。
最好的方法是扩展 AddClientToCompany()
以分配双方:
public class Company
{
...
public virtual void AddClientToCompany(Client client)
{
clients.Add(client);
// essential line
client.Company = this;
}
...
和运行时代码:
var client = new Client
{
...
}
var company = new Company
{
...
}
// no company knows about client
// and client knows abtou company
company.AddClientToCompany(client);
session.Save(company);
NHibernate 现在将正确地注入具有相关实体 ID 的 INSERT...
毕竟,我们必须真正确定的是,参考映射是可编辑的 - 而不是 属性:
<property name="CompanyId" column="CompanyId" type="int"
insert="false" update="false" >
// the above must be insert and update false
// the below must be editable - it is a reference - managed by NHibernate
<many-to-one name="Company"
class="ConsoleApplication1.Company, ConsoleApplication1"
column="CompanyId" cascade="none"/>