由于已插入记录的意外更新导致Nhibernate外键约束

时间:2013-02-01 19:47:24

标签: sql nhibernate transactions

这是一个奇怪的复制在以下代码中:

        using (ISession session = RepositoryTestHelper.SessionFactory.OpenSession())
        {
            //session.BeginTransaction();

            UserRepo repo = new UserRepo(session);
            CompanyRepo cRepo = new CompanyRepo(session);
            var user = repo.FindByEmail("test.user@blah.com");
            user.CompanyAssociations.Add(new CompanyUserAssoc() 
                { 
                    User = user,
                    Company = cRepo.GetById(1)
                });
            repo.AddOrUpdate(user);

            //session.Transaction.Commit();
        }

用户,公司和CompanyUserAssoc之间的关系非常简单:

对于公司:

HasMany<CompanyUserAssoc>(x => x.UserAssociations).KeyColumn("User_id");

对于用户:

HasMany<CompanyUserAssoc>(x => x.CompanyAssociations).KeyColumn("Company_id")

对于关联类本身:

References(x => x.Company).UniqueKey("CompanyId_UserId");
References(x => x.User).UniqueKey("CompanyId_UserId");

现在这是我感到困惑的地方。请注意,在我的初始代码中,begin和commit trans调用已被注释掉。这实际上意味着代码将工作! CompanyUserAssoc已创建并正确引用id为1的用户和公司。<!p>

但是......遗憾的是,当我把它放在一个交易中时,我得到了这个错误:

{"The UPDATE statement conflicted with the FOREIGN KEY constraint \"FK3C47859753A62C6E\". The conflict occurred in database \"xxxx\", table \"dbo.Company\", column 'Id'.\r\nThe statement has been terminated."}

但为什么呢?那是我的问题。我在分析器中看到的是它这样做:

exec sp_executesql N'UPDATE [CompanyUserAssoc] SET Company_id = null WHERE Company_id = @p0',N'@p0 int',@p0=1

等等......什么?空值?为什么将公司ID设置为null?为什么它只在交易中这样做?我的Nhibernate映射有什么“错误”?

2 个答案:

答案 0 :(得分:0)

由于两个集合都映射为非反向(the default)且公司集合没有用户,因此它将发出该更新以清除链接表。您可以尝试将UserAssociations设置为反向吗?或者,当涉及显式链接表时,我通常会做的是将HasMany设置为反向,并直接使用链接表。

答案 1 :(得分:0)

最后这是一只红鲱鱼,我已经开始鄙视这条鱼了。我没有注意到我的匆忙和对intellisense的依赖,公司的UserAssocations属性不是IList而是IList!是的,我愚蠢地选择了Nhib地图类而不是域类..这奇怪地没有你想象的方式错误,并且没有交易,但为什么?

嗯 - Nhib能够插入assoc条目,但后来认为它需要用已插入的id更新同一个表(因为它以某种方式将其视为一个不同的实体?)。我本来期望在map类本身中出现编译错误,因为我使用的是类型,但没有。没有事务,sql生成的工作。

我会更多地调查为什么,但我已经回答了这个问题,只是为了突出一个罕见且愚蠢的错误,如果错过了可能导致大量调查。