这是一个奇怪的复制在以下代码中:
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映射有什么“错误”?
答案 0 :(得分:0)
由于两个集合都映射为非反向(the default)且公司集合没有用户,因此它将发出该更新以清除链接表。您可以尝试将UserAssociations
设置为反向吗?或者,当涉及显式链接表时,我通常会做的是将HasMany
设置为反向,并直接使用链接表。
答案 1 :(得分:0)
最后这是一只红鲱鱼,我已经开始鄙视这条鱼了。我没有注意到我的匆忙和对intellisense的依赖,公司的UserAssocations属性不是IList而是IList!是的,我愚蠢地选择了Nhib地图类而不是域类..这奇怪地没有你想象的方式错误,并且没有交易,但为什么?
嗯 - Nhib能够插入assoc条目,但后来认为它需要用已插入的id更新同一个表(因为它以某种方式将其视为一个不同的实体?)。我本来期望在map类本身中出现编译错误,因为我使用的是类型,但没有。没有事务,sql生成的工作。
我会更多地调查为什么,但我已经回答了这个问题,只是为了突出一个罕见且愚蠢的错误,如果错过了可能导致大量调查。