NHibernate的 - 当添加一个目的是一个多到多的收集,现有的对象被移除和重新插入 [英] NHibernate - When adding an object to a many-to-many collection, existing objects are removed and reinserted

查看:140
本文介绍了NHibernate的 - 当添加一个目的是一个多到多的收集,现有的对象被移除和重新插入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用许多一对多映射表映射领域对象。

I'm using a many-to-many mapping table which maps fields to objects.

相关数据库结构...

Relevant DB structure...

对象:表
(PK)OBJECTID
[剩下的就是无关紧要]

Objects: Table
(pk) objectId
[ the rest is irrelevant ]

字段:表
(PK)fieldId
[剩下的就是无关紧要]

Fields: Table
(pk) fieldId
[ the rest is irrelevant ]

ObjectFields:表
(PK)fieldObjectid (FK)fkObjectId - >对象 (FK)fkFieldId - >字段

ObjectFields: Table
(pk) fieldObjectid (fk) fkObjectId -> Objects (fk) fkFieldId -> Fields

我的映射是这样的:

<bag name="Fields" table="ObjectFields" lazy="true" cascade="all">
  <key column="fkObjectId"/>
  <many-to-many class="Field" column="fkFieldId" />
</bag>

现在,所有集合操作都如你所愿 - 检索,添加和删除。然而,有一个很奇怪的事情发生。如果我的对象添加到字段集合,NHibernate的删除哪些已经存在,并重新插入它。

Now, all collection operations work as you would expect - retrieving, adding and deleting. However, there is a very odd thing happening. If I add an object to the "Fields" collection, NHibernate deletes what is already there and reinserts it.

下面是我的log4net的转储: DEBUG NHibernate.SQL [(空)] - 选择this_.objectId为objectId6_0_,this_.Name为Name6_0_,this_.Description为Descript3_6_0_,this_.RootElement为RootElem4_6_0_,this_.ChildElement为ChildEle5_6_0_,this_.ImageUrl为ImageUrl6_0_,this_.hasChildren作为hasChild7_6_0_,this_.CreateStamp作为CreateSt8_6_0_从对象THIS_ WHERE this_.objectId = @ P0; @ P0 = 5 [类型:的Int32(0)]
DEBUG NHibernate.SQL [(空)] - 选择fields0_.fkObjectId为fkObjectId1_,fields0_.fkFieldId为fkFieldId1_,inventoryf1_.fieldId为fieldId4_0_,inventoryf1_.fieldName为fieldName4_0_,inventoryf1_.fieldType为fieldType4_0_,inventoryf1_.Required作为Required4_0_从ObjectFields fields0_离开外连接字段inventoryf1_上fields0_.fkFieldId = inventoryf1_.fieldId WHERE fields0_.fkObjectId=@p0; @ P0 = 5 [类型:的Int32(0)]
DEBUG NHibernate.SQL [(空)] - 选择this_.fieldId为fieldId4_0_,this_.fieldName为fieldName4_0_,this_.fieldType为fieldType4_0_,this_.Required作为Required4_0_ FROM字段THIS_ WHERE this_.fieldId = @ P0; @ P0 = 2 [类型:的Int32(0)]
DEBUG NHibernate.SQL [(空)] - DELETE FROM ObjectFields WHERE fkObjectId = @ P0; @ P0 = 5 [类型:的Int32(0)]
DEBUG NHibernate.SQL [(空)] - INSERT INTO ObjectFields(fkObjectId,fkFieldId)VALUES(@ P0,P1 @)@ P0 = 5 [类型:的Int32(0)],@ P1 = 1 [类型:的Int32(0 )]
DEBUG NHibernate.SQL [(空)] - INSERT INTO ObjectFields(fkObjectId,fkFieldId)VALUES(@ P0,P1 @)@ P0 = 5 [类型:的Int32(0)],@ P1 = 2 [类型:的Int32(0 )]

Here is my log4net dump: DEBUG NHibernate.SQL [(null)] - SELECT this_.objectId as objectId6_0_, this_.Name as Name6_0_, this_.Description as Descript3_6_0_, this_.RootElement as RootElem4_6_0_, this_.ChildElement as ChildEle5_6_0_, this_.ImageUrl as ImageUrl6_0_, this_.hasChildren as hasChild7_6_0_, this_.CreateStamp as CreateSt8_6_0_ FROM Objects this_ WHERE this_.objectId = @p0;@p0 = 5 [Type: Int32 (0)]
DEBUG NHibernate.SQL [(null)] - SELECT fields0_.fkObjectId as fkObjectId1_, fields0_.fkFieldId as fkFieldId1_, inventoryf1_.fieldId as fieldId4_0_, inventoryf1_.fieldName as fieldName4_0_, inventoryf1_.fieldType as fieldType4_0_, inventoryf1_.Required as Required4_0_ FROM ObjectFields fields0_ left outer join Fields inventoryf1_ on fields0_.fkFieldId=inventoryf1_.fieldId WHERE fields0_.fkObjectId=@p0;@p0 = 5 [Type: Int32 (0)]
DEBUG NHibernate.SQL [(null)] - SELECT this_.fieldId as fieldId4_0_, this_.fieldName as fieldName4_0_, this_.fieldType as fieldType4_0_, this_.Required as Required4_0_ FROM Fields this_ WHERE this_.fieldId = @p0;@p0 = 2 [Type: Int32 (0)]
DEBUG NHibernate.SQL [(null)] - DELETE FROM ObjectFields WHERE fkObjectId = @p0;@p0 = 5 [Type: Int32 (0)]
DEBUG NHibernate.SQL [(null)] - INSERT INTO ObjectFields (fkObjectId, fkFieldId) VALUES (@p0, @p1);@p0 = 5 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)]
DEBUG NHibernate.SQL [(null)] - INSERT INTO ObjectFields (fkObjectId, fkFieldId) VALUES (@p0, @p1);@p0 = 5 [Type: Int32 (0)], @p1 = 2 [Type: Int32 (0)]

正如你所看到的,它的发行delete语句,然后重新插入。

As you can see, it's issuing delete statements and then reinserting.

任何想法如何prevent呢?

Any ideas how to prevent this?

推荐答案

总之,箱包作用一样,你应该使用其他类型的集合。在这里,你必须从NHibernate的文档很好的解释,但我remomend您阅读全篇(的 17.5。理解集合的性能

In short, bags behave like that, you should use another type of collection. Here you have a good explanation from NHibernate doc but I remomend you to read the whole chapter (17.5. Understanding Collection performance

所有的有序集合(地图,列表,数组)都拥有一个由和索引列的主键。在这种情况下集合类的更新是非常高效的 - 主键已经被有效的索引和特定行可能会在NHibernate的尝试更新或删除,可以迅速找到

All indexed collections (maps, lists, arrays) have a primary key consisting of the and index columns. In this case collection updates are usually extremely efficient - the primary key may be efficiently indexed and a particular row may be efficiently located when NHibernate tries to update or delete it.

设定有包括键和元素组成的主键。这可能对某些类型的收集装置,特别是组合元素或文本或二进制大字段的效率较低;数据库可能无法索引一个复杂的主键efficently。另一方面,对于一对多或多对多关联,尤其是合成的标识符的情况下,它很可能是一样有效的。 (边注:如果你希望SchemaExport为创建一组为您的主键,您必须声明为不空=真的所有列)

Sets have a primary key consisting of key and element columns. This may be less efficient for some types of collection element, particularly composite elements or large text or binary fields; the database may not be able to index a complex primary key as efficently. On the other hand, for one to many or many to many associations, particularly in the case of synthetic identifiers, it is likely to be just as efficient. (Side-note: if you want SchemaExport to actually create the primary key of a set for you, you must declare all columns as not-null="true".)

idbag映射定义了代理键,因此它总是可以很高效的被更新。事实上,他们是最好的情况。

idbag mappings define a surrogate key, so they are always very efficient to update. In fact, they are the best case.

袋子是最坏的情况。因为bag允许重复的元素值,也没有索引字段,没有主键可以定义。 NHibernate的没有办法重复的行了。 NHibernate的通过完全删除(在一个单一的DELETE),并重新集合时,它改变了解决此问题。这可能是非常低效的。

这篇关于NHibernate的 - 当添加一个目的是一个多到多的收集,现有的对象被移除和重新插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆