关于 asp.net:使用 nhibernate 将外键更新为 Null 值

Updating a foreign key to Null value using nhibernate

我有两个表 BuildGroup 和表 DocumentTemplate。 DocumentTemplate 表具有 BuildGroupId 作为可以为空的外键。在某个场景中,我更新了 DocumentTemplate 表中的 BuildGroupId。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public bool EditDocTempForBldGrp(int docId, int bldGrpId)
    {
        try
        {
            using (ISession session = Document.OpenSession())
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    HSDocumentTemplate objDocBO = new HSDocumentTemplate();

                    objDocBO = GetDocumentDetailsById(docId);
                    HSBuildGroup objBldGrp = new HSBuildGroup();

                    if (bldGrpId != 0)
                    {                            
                        objBldGrp.Id = bldGrpId;
                    }
                    else
                    {
                        //int ? bldid = null;
                        //objDocBO.HSBuildGroup.Id = null;
                        //objDocBO.HSBuildGroup.Id = DBNull.Value;
                        //objDocBO.HSBuildGroup.Id = -1;

                    }
                    objDocBO.HSBuildGroup = objBldGrp;
                    session.Update(objDocBO);
                    transaction.Commit();
                }
            }
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            return false;
        }

    }

在另一个场景中,我需要再次将 DocumentTemplate 表中的 BuildGroupId 设置为
dbnull.value。我尝试了不同的情况,如在 else 块中。它给出了错误:不能
将类型 \\'System.DBNull\\' 隐式转换为 \\'int\\'。
如何使用 NULL 更新外键值?任何帮助将不胜感激。


一些观察:

  • 您不应将 Id 分配给 HSBuildGroup 对象,而应通过 Session.Load() 加载实例,以防 bldGrpId 不为 0。
  • 您可以像这样将文档的构建组设置为空:

    objDocBO.HSBuildGroup = null;

    NHibernate 会处理剩下的事情。

希望对您有所帮助。


正如 Kay Herzam 所说,使用 Session.Load 和 null。

您必须确定文件存在才能调用 session.Load。示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
public bool EditDocTempForBldGrp(int docId, int bldGrpId)
{
    try
    {
        using (ISession session = Document.OpenSession())
        using (ITransaction transaction = session.BeginTransaction())
        {
           session.Get<HSDocumentTemplate>(docId).HSBuildGroup
                      = bldGrpId = 0 ? null : session.Load<HSBuildGroup>(bldGrpId);
               transaction.Commit();
        }
    }
}

这样,nhibernate 会执行类似的操作,

1
2
select ... from DocumentTemplate where DocId = ..;
UPDATE DocumentTemplate SET .... , BuildGroupId = null where DocumentId = XX;

1
2
select ... from DocumentTemplate where DocId = ..;
UPDATE DocumentTemplate SET .... , BuildGroupId = YY where DocumentId = XX;

请注意,没有选择 BuildGroup 到数据库。

如果您不确定构建组的存在,您的代码应如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
public bool EditDocTempForBldGrp(int docId, int bldGrpId)
{
        try
        {
            using (ISession session = Document.OpenSession())
            using (ITransaction transaction = session.BeginTransaction())
            {
               session.Get<HSDocumentTemplate>(docId).HSBuildGroup
                      = session.Get<HSBuildGroup>(bldGrpId);
               transaction.Commit();
            }
         }
}

这样,nhibernate 会执行类似的操作,

1
2
3
select ... from DocumentTemplate where DocId = ..;
SELECT .... FROM BuildGroup where buildgroupid = ZZ;
UPDATE DocumentTemplate SET .... , BuildGroupId = null where DocumentId = XX;

如果对象不存在,Get 会自动返回 null。

最后你不需要调用 Session.Update() 这是为了重新附加一个实体。提交事务时,与 Session 关联的所有内容都将被刷新。