NHibernate 级联删除出错的问题

又是违规昵称 2007-08-16 11:51:50
有一个student类,与team是多对一关系,在student表中有一个teamid的字段.
我现在想删除一个team,那么team中所有的student也应该被删除

问题是,如果我在student表中将teamid设为允许为空,那么对应的student可以正常地被删除.而如果teamid不允许为空,那么就会抛出一个异常:

could not delete collection: [ClassLibrary1.Team.Students#1]

它的innerException是:
{"Cannot insert the value NULL into column 'TeamID', table 'DB_ManyToOne.dbo.T_Student'; column does not allow nulls. UPDATE fails.\r\nThe statement has been terminated."}

这个问题怎么解决呢?我总不能不设置外键吧?
谢谢回答

...全文
842 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
又是违规昵称 2007-08-22
  • 打赏
  • 举报
回复
此问题已经结贴
谢谢大家回答
siky231 2007-08-17
  • 打赏
  • 举报
回复
假设我有一个表有id跟name字段,id为主码,能否利用Criteria查询根据id的值返回name的值啊
又是违规昵称 2007-08-17
  • 打赏
  • 举报
回复
今天怎么没人回贴了啊?
难道我一定得cascade = "none",然后先删Student,才能再删Team吗?
又是违规昵称 2007-08-17
  • 打赏
  • 举报
回复
siky2310()你说的是QBC查询方法吧?
既然你有id,那么你肯定能获得它的对象实体
既然有了实体,那个怎么会得不到name呢?

问个小问题
你怎么找到我这里来了?
又是违规昵称 2007-08-16
  • 打赏
  • 举报
回复
嗯,这样是可以做的,但是我在配置文件里面写了cascade="all"就是为了达到级联删除的效果
这样用NHibernate才有意思啊
txt_ly 2007-08-16
  • 打赏
  • 举报
回复
换一种思路行不行,执行两个删除语句
先delete from student where teamid=4
再 delete from team where id=4



又是违规昵称 2007-08-16
  • 打赏
  • 举报
回复
难道大家都吃饭去了吗?
在线等...
又是违规昵称 2007-08-16
  • 打赏
  • 举报
回复
但是我的TeamID不能允许为空,没有办法解决....
又是违规昵称 2007-08-16
  • 打赏
  • 举报
回复
我还是把配置文件和代码贴上来吧
Student.cs文件:

using System;
using System.Collections.Generic;
using System.Text;
using Iesi.Collections;
using System.Collections;

namespace ClassLibrary1
{
public class Student
{
private int _StudentID;
private string _StudentName;
private Team _Team;

public virtual int StudentID
{
set { _StudentID = value; }
get { return _StudentID; }
}

public virtual string StudentName
{
set { _StudentName = value; }
get { return _StudentName; }
}

public virtual Team team
{
set { _Team = value; }
get
{
//if (team == null) _Team = new Team();
return _Team;
}
}
}
}

Team.cs文件:
using System;
using System.Collections.Generic;
using System.Text;
using Iesi.Collections;

namespace ClassLibrary1
{
public class Team
{
private int _TeamID;
private string _TeamName;
private ISet _Students;

public virtual int TeamID
{
set { _TeamID = value; }
get { return _TeamID; }
}

public virtual string TeamName
{
set { _TeamName = value; }
get { return _TeamName; }
}

public virtual ISet Students
{
set { _Students = value; }
get { return _Students; }
}
}
}

Student.hbm.xml文件:

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="ClassLibrary1" assembly="ClassLibrary1">

<class name="ClassLibrary1.Student" table="T_Student">
<id name="StudentID" column="StudentID">
<generator class="identity" />
</id>
<property name="StudentName" column="StudentName"/>
<many-to-one name="team" column ="TeamID" class="ClassLibrary1.Team" cascade="all" outer-join="true"
access="property"/>

</class>

</hibernate-mapping>

Team.hbm.xml文件:
<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="ClassLibrary1" assembly="ClassLibrary1">

<class name="ClassLibrary1.Team" table="T_Team">
<id name="TeamID" column="TeamID" unsaved-value="0">
<generator class="identity" />
</id>
<property name="TeamName" column="TeamName"/>

<set name ="Students" cascade="all" inverse="false" lazy="false" table="T_Student">
<key column="TeamID"/>
<one-to-many class="ClassLibrary1.Student"/>
</set>

</class>
</hibernate-mapping>

我在页面里面是这样写的,就几句话:
using System;
using System.Data;
//using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using NHibernate;
using NHibernate.Cfg;
using ClassLibrary1;
using System.Collections;
using NHibernate.Expression;


public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ISessionFactory factory = new Configuration().Configure().BuildSessionFactory();
ISession session = factory.OpenSession();
ITransaction trans = session.BeginTransaction();

//----------------删除本组后也删除本组所有的学生----------
Team team1 = session.Get(typeof(Team), 1) as Team;
session.Delete(team1);
trans.Commit();
}
}

执行删除了就抛了一个插入空值的异常
但要是在数据库表里允许TeamID为空,那么就可以正常级联删除

问了下同事,同事说,可能NHibernate在执行删除的时候先将对应的外键置为null
然后再删除为null的数据列的,不知道是不是这样

txt_ly 2007-08-16
  • 打赏
  • 举报
回复
teamid不允许为空,但是你插入新记录column 'TeamID'为空了
txt_ly 2007-08-16
  • 打赏
  • 举报
回复
不是删除的问题吧,是你插入数据的问题
又是违规昵称 2007-08-16
  • 打赏
  • 举报
回复
一直等到5点半...
不行明天接着等~~~~

又是违规昵称 2007-08-16
  • 打赏
  • 举报
回复
我觉得,既然NHibernate有级联删除的功能,那么它设计的时候肯定就考虑过了数据库外键字段不允许为空的情况的

还是希望能在这一点上得到解决
先谢谢大家的热心回答

继续等待
mingjunr 2007-08-16
  • 打赏
  • 举报
回复
好像必须设成可空
删除的过程大概是,首先删除team,并把student表teamid字段设为NULL,第二步才是删除student.
内部机制是什么样的没研究过,删除的过程是这样的
又是违规昵称 2007-08-16
  • 打赏
  • 举报
回复
楼上的信息对我很重要,这点我确实没有注意到,先谢谢了
但是我简单地写成属性后,仍然有错误

Could not compile the mapping document: ClassLibrary1.Student.hbm.xml

内部错误是:
{"could not determine a property type for: team"}
不能为属性team决定一个类型

我试着为其指定int类型和ClassLibrary1.Team均不能成功

能再仔细地给我说说原因吗?
Visual00000000 2007-08-16
  • 打赏
  • 举报
回复
一对多映射分为单向映射和双向映射
对于单向的one-to-many映射,cascade过程中会用到把student表的teamid设置为Null,所以teamid应设为允许NULL;
双向one-to-many映射,建议把T_student的teamid设置为不允许NULL

他们的配置文件有些不同
楼主的是双向映射格式,所以会发生异常
单向映射(允许teamid为NULL),Student.hbm.xml文件中则不需要配置
<many-to-one name="team" column ="TeamID" class="ClassLibrary1.Team" cascade="all" outer-join="true"
access="property"/>
只要简单的写成属性即可
<property name="team" column="TeamID"/>
又是违规昵称 2007-08-16
  • 打赏
  • 举报
回复
up.....着急啊~~~~
又是违规昵称 2007-08-16
  • 打赏
  • 举报
回复
怎么还没有人来回答啊...

111,097

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧