English 中文(简体)
NHibernate list Save andloading 最佳建议
原标题:NHibernate list saving and loading optimization advice

我有3个班级,分布在NHibernate:Intersection, 车辆和区。

我的科际班有一个属于科际的区名单。 我的车辆舱内有一份载运车辆的区域清单。 最后,我的区级载有载有该区车辆清单。

我的测试性能包括10 000辆汽车和500个区和250个科。 我在标明清单的区和车辆上装载的时间是所有这些物体的27分钟左右。

我不敢肯定正在做些什么,但这两个清单并非最优化。 如果我把车辆清单从安全区分类图中删除,则在保存物体方面有10分钟的差异。 这似乎只是看2个名单如何直接相关。

看来,NHibernate正在收回名单上的物品,并在储蓄程序中增加间接费用。 是否有办法优化这些清单,以便更快地节省物体?

Here are my mappings for Device which both my Intersection and Vehicle inherit from:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Devices.Device, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Device`">
    <id name="PK" type="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="PK" />
      <generator class="identity" />
    </id>
    <version name="LastModifiedOn" column="LastModifiedOn" type="timestamp" access="field.pascalcase-underscore" />
    <joined-subclass name="EMTRAC.Intersections.Intersection, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
      <key>
        <column name="Device_id" />
      </key>      
      <component name="Zones" access="property">
        <bag name="_list" cascade="all-delete-orphan" access="field" fetch="join" inverse="false">
          <key>
            <column name="Zone_PK" />
          </key> 
          <many-to-many class="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        </bag>
      </component>
      <property name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <column name="ID" />
      </property>
    </joined-subclass>
    <joined-subclass name="EMTRAC.Vehicles.Vehicle, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
      <key>
        <column name="Device_id" />
      </key>      
      <component name="Zones" access="property">
        <bag name="_list" cascade="save-update" access="field" table="VehicleZones" inverse="true">
          <key>
            <column name="veh_id" not-null="true"/>
          </key>
          <many-to-many class="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        </bag>
      </component>
      <property name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <column name="ID" />
      </property>           
    </joined-subclass>
  </class>
</hibernate-mapping>    

最后,我为安全区分类绘制了地图:

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Zone`">
    <id name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="PK"/>
      <generator class="identity" />
    </id>
    <version name="LastModifiedOn" column="LastModifiedOn" type="timestamp" access="field.pascalcase-underscore" />
    <property name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="ID" />
    </property>    
    <component name="Vehicles" access="property">
      <bag name="_list" cascade="save-update" access="field" table="VehicleZones">
        <key>
          <column name="veh_id" not-null="true"/>
        </key>
        <many-to-many class="EMTRAC.Vehicles.Vehicle, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </bag>
    </component>
  </class>
</hibernate-mapping>

关于如何提高这些清单的效率的任何想法? 现在每张表格都保存了50万份记录,当然装上这些记录,并节省了许多记录的时间。

我删除了我遗忘的“false”部分,并且大大加快了。 我还对物品的节约和装载作了一些调整,将部件分解成单独的线,以提高性能,并在NHibernate使用交易似乎有所帮助。

然而,我已经走进了一条 s。 现在我无法挽救这两个名单。 我在把名单添加到车辆和区之前,先挖掘了我的所有交叉点、车辆和区。 然而,如果我列入安全区制图中的车辆清单,我就发现一个试图更新车辆和清单的错误。 该守则是:

using (var tx = session.BeginTransaction())
{
    foreach (Vehicle vehicle in Program.data.Vehicles.list)
    {
        session.Update(vehicle);
    }
    tx.Commit();
}

我收到了一个Sack Overflow例外。 任何想法?

如何做到这一点的想法?

Is there no way to map the list of Vehicles in the Zone class and the list of Zones in the Vehicle class to the same table so it is not iterating through both lists recursively? The lists are related to each other. One is a list of Zones that a Vehicle belongs to and the other is a list of Vehicles that a Zone belongs to. I don t think I have that mapped correctly after digging more into this.

EDIT I have been making progress with the correct mappings I believe. I posted a more simplified version of the mappings for Device which maps the Intersection and Vehicle classes along with a simplified version of Zone which of course maps the Zone class.

除了一个例外,这似乎节省了相对较好的费用。 由于某种原因,大量物品的节省将消除斯纳克多里的例外情况。 这里,我使用的是:

//  Create a Transaction for batch updating
using (var tx = session.BeginTransaction())
{
    foreach (Vehicle veh in Program.data.Vehicles.list)
    {
        session.Save(veh);
    }
    //  Commit transactions
    tx.Commit();
}

This works fine for say 250 Intersections, 500 zones, and 1000 Vehicles. However, I was attempting to create a test set of data to stress this in a more extreme environment and bumped up to 2400 Intersections, 9600 Zones, and 5000 Vehicles and I run across a Stack Overflow exception when trying to save the test data into the database via this manner.

任何想法?

最佳回答

其实,这实际上又 saving了他们。 b/c 我的地图不正确。 我需要一方的反向关系,然后我需要修改地图,以指明外国钥匙。 最后,我需要一个经过改良的实地,告诉国家,该项目已经修改,需要更新。

以下是正确的地图:

车辆:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Devices.Device, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Device`">
    <id name="PK" type="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="PK" />
      <generator class="identity" />
    </id>
    <version name="LastModifiedOn" column="LastModifiedOn" type="timestamp" access="field.pascalcase-underscore" />
    <joined-subclass name="EMTRAC.Vehicles.Vehicle, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
      <key>
        <column name="Device_id" />
      </key>      
      <component name="Zones" access="property">
        <bag name="_list" cascade="save-update" access="field" table="VehicleZones" inverse="true">
          <key>
            <column name="veh_id" not-null="true"/>
          </key>
          <many-to-many class="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        </bag>
      </component>
      <property name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <column name="ID" />
      </property>     
  </class>
</hibernate-mapping>

Zone:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Zone`">
    <id name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="PK"/>
      <generator class="identity" />
    </id>
    <version name="LastModifiedOn" column="LastModifiedOn" type="timestamp" access="field.pascalcase-underscore" />
    <property name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="ID" />
    </property>    
    <component name="Vehicles" access="property">
      <bag name="_list" cascade="save-update" access="field" table="VehicleZones">
        <key>
          <column name="veh_id" not-null="true"/>
        </key>
        <many-to-many class="EMTRAC.Vehicles.Vehicle, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </bag>
    </component>
  </class>
</hibernate-mapping>
问题回答

尽管我不是回答,但我建议NHibernate是挽救500K记录的最佳办法,尽管我承认,有时很难用(例如)储存的程序来取代这部法典。

你可以考虑举行无国籍会议,因为这样做可以选择速度,但不会改变目标。 另一件事是找到正在执行的内容。 你们是否看到你不期望的更新? 在这种情况下,你的绘图档案中可能有错误。

归根结底,如果您进行大量数据改动,那么国家卫生局需要将数据输入非行,并且需要跟踪装载物体,以跟踪这些变化。 在500K记录中,这收集了大量数据以保存记忆。

It appears NHibernate is recursively saving the items within both the lists

you don t have to guess; nhibernate has great logging mechanisms that show you exactly what sql is generated. It might be a good idea to see what exactly it does and post it back here for analysis.

secondly, nHib is not really intended for these kinds of volumes of data.
see the suggestions I received here.
the best advice I can give you is the same one I received- don t load 10,000 objects into memory at once! It s just not good practice, not matter what data access method you re using.





相关问题
nHibernate one-to-many inserts but doesnt update

Instead of getting into code, I have a simple question. Default behavior for a simple one-to-many is that it inserts the child record then updates the foreign key column with the parent key. Has ...

How Do I copy an existing nhibernate object as a new object?

I a persisted NHibernate object that I would like to repersist as a new entity. How do I get NHibernate to save this object as if it was a new? I am thinking I might create a session interceptor to ...

join across databases with nhibernate

I am trying to join two tables that reside in two different databases. Every time, I try to join I get the following error: An association from the table xxx refers to an unmapped class. If the ...

WPF - MVVM - NHibernate Validation

Im facing a bit of an issue when trying to validate a decimal property on domain object which is bound to a textbox on the view through the viewmodel. I am using NHibernate to decorate my property on ...

NHibernate Search in a List using ICriteria

I have my class X : public class ClassX { public virtual IList<ClassY> ListY { get; set; } ... } My ClassX mapping (using Fluent) ... HasMany<ClassX>(x => x.ListY ) ....

热门标签