我有一个名为ShoppingLists
的模型,每个ShoppingLists
都有一个名为ShoppingListItems
的{{1}}集合。我喜欢能够做的是在我的列表中添加一个新项目:
Items
我希望dbList.Items.Add(new ShoppingListItems(Guid.NewGuid(), identity.UserId, source.Raw));
自动链接到其父ShoppingListItems
类,并且NHibernate在事务时创建适当的SQL ShoppingLists
语句承诺。但是,我得到了例外:
INSERT
我需要做的是创建对象,保存它,然后将其添加到集合中:
NHibernate.StaleStateException was unhandled
HResult=-2146232832
Message=Unexpected row count: 0; expected: 1
Source=NHibernate
我想消除这样做的必要性。我对var newItem = new ShoppingListItems(Guid.NewGuid(), identity.UserId, source.Raw);
newItem.ShoppingList = dbList;
session.Save(newItem);
dbList.Items.Add(newItem);
的映射是这样的:
ShoppingLists
我对Id(x => x.ShoppingListId);
Map(x => x.UserId).Not.Nullable();
Map(x => x.Title).Not.Nullable();
HasMany(x => x.Items)
.KeyColumn("ShoppingListId")
.Cascade.Delete(); // If Shopping List is deleted, delete all the Items that reference this list
的映射是:
ShoppingListItems
我尝试过各自使用Id(x => x.ItemId);
Map(x => x.Raw).Length(50);
Map(x => x.Qty);
Map(x => x.Unit);
Map(x => x.UserId).Not.Nullable();
Map(x => x.CrossedOut).Not.Nullable();
References(x => x.Recipe).Column("RecipeId");
References(x => x.Ingredient).Column("IngredientId");
References(x => x.ShoppingList).Column("ShoppingListId");
,但不能避免。有什么想法吗?
答案 0 :(得分:1)
此处的问题与处理的ShoppingListItem
Guid ID 有关(请参阅问题中的项目创建的代码段)。
“工作”方案,在创建并保留ShoppingListItem
时,执行以下步骤 - 生成Guid
ID并将其传递给构造函数
var newItem = new new ShoppingListItems(Guid.NewGuid()...)
接下来,要求NHiberante执行session.Save(newItem)
,因此发出INSERT语句......
但是在第二种情况下会发生什么情况,当session.Save(newItem)
未被调用时,只有Add()
项目进入父ShoppingLists
的集合?
如上所述:5.1.4.7. Assigned Identifiers(摘录)
...使用已分配的生成器的实体无法通过ISession的
SaveOrUpdate()
方法保存。相反,如果要保存或更新对象,则必须明确指定NHibernate ...
NHibernate在这种情况下做什么(当调用session.Flush()
时)猜测:应该为每个集合项发出INSERT还是UPDATE?
说到newItem
,它会将Guid
ID与UnsavedValue()
进行比较,在这种情况下为Guid.Empty
。
此比较将导致决定:发出UPDATE语句,Guid ID不代表新对象。
执行UPDATE。数据库响应:已完成更新,无错误,但 无行已更新*。 NHibernate抛出:
意外的行数:0;预期:1
将GUID生成留在NHibernate上。 E.g:
Id(x => x.ItemId)
.GeneratedBy.GuidComb()
.UnsavedValue(Guid.Empty);
而且,明确地将newItem
引用设置为其父级,使用Inverse()设置优化级联
// both assignments
newItem.ShoppingList = dbList;
dbList.Items.Add(newItem);
使用inverse映射的列表:
// improved write operations handling
HasMany(x => x.Items)
.KeyColumn("ShoppingListId")
.Inverse()
...
答案 1 :(得分:0)
请重新检查ShoppingListItems的映射
你必须做一个级联全部,反过来应该是真的
购物清单和商品之间存在双向关联。
您可以通过将两个多对多关联映射到同一个数据库表并将一端声明为反向来指定双向多对多关联。