0

私は Entity Framework 4.4、NHibernate 3.3.1.4000、および SQL Server を試してきましたが、変更をコミットするときに関係を修正する際に違いがあることに気付きました。何か間違ったことをしている。

これが私がテストしたものです。私はn人の子供にリンクされた古典的な親を持っています。データベースには、それぞれ 20 人の子供を持つ 2 人の親がいます。両方の親をロードし、最初の親の最初の子を取得して、その子を 2 番目の親に割り当てます。次に、変更をコミットします。

EF では、保存した後、両方の親の Children コレクションの数が変更されていることがわかり、関係が修正されました。

ただし、NHibernate で同じことを行うと、カウントは変わりません。

問題を再現するための私のコード設定は次のとおりです。

POCO:

public class Parent
{
    public virtual int ParentId { get; set; }

    public virtual string Name { get; set; }

    public virtual IList<Child> Children { get; set; }

    public Parent()
    {
        Children = new List<Child>();
    }
}

public class Child
{
    public virtual int ChildId { get; set; }

    public virtual int ParentId { get; set; }

    public virtual string Name { get; set; }

    public virtual Parent Parent { get; set; }
}

Hibernate 親マッピング:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="ConsoleApplication1"
                   namespace="ConsoleApplication1">
  <class name="Parent" table="Parents">
    <id name="ParentId" column="ParentId" />
    <property name="Name" column="Name" />
    <bag name="Children" cascade="all">
      <key column="ParentId"/>
      <one-to-many class="Child"/>
    </bag>
  </class>
</hibernate-mapping>    

Hibernate 子マッピング:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="ConsoleApplication1"
                   namespace="ConsoleApplication1">
  <class name="Child" table="Children">
    <id name="ChildId" column="ChildId" />
    <property name="Name" column="Name" />
    <many-to-one name="Parent" class="Parent" column="ParentId" not-null="true" />
  </class>
</hibernate-mapping>    

EF Db コンテキスト:

public class Entities : DbContext
{
    public DbSet<Parent> Parents { get; set; }

    public DbSet<Child> Children { get; set; }
}

App.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler,NHibernate" />
  </configSections>
  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="connection.provider">
        NHibernate.Connection.DriverConnectionProvider
      </property>
      <property name="dialect">
        NHibernate.Dialect.MsSql2005Dialect
      </property>
      <property name="connection.driver_class">
        NHibernate.Driver.SqlClientDriver
      </property>
      <property name="connection.connection_string">
        Data Source=localhost;Initial Catalog=MaintainRelationshipsNH;Integrated Security=True;
      </property>
    </session-factory>
  </hibernate-configuration>
  <connectionStrings>
    <add
      name="Entities"
      providerName="System.Data.SqlClient"
      connectionString="Server=localhost;Database=MaintainRelationshipsNH;Trusted_Connection=true;"/>
  </connectionStrings>
</configuration>

テーブルとデータを作成するスクリプト:

create table Parents (
   ParentId INT not null,
   Name NVARCHAR(255) null,
   primary key (ParentId)
)

create table Children (
   ChildId INT not null,
   Name NVARCHAR(255) null,
   ParentId INT not null,
   primary key (ChildId)
)

alter table Children
    add constraint FK_Children_Parents
    foreign key (ParentId)
    references Parents

declare @idChild int        
insert into Parents (ParentId, Name) values (0, 'John');
set @idChild = 0
while @idChild < 20
begin
   insert into Children (ChildId, Name, ParentId) values (@idChild, 'Child ' + convert(nvarchar(2), @idChild), 0);
   set @idChild = @idChild + 1
end
insert into Parents (ParentId, Name) values (1, 'Julie');
while @idChild < 40
begin
   insert into Children (ChildId, Name, ParentId) values (@idChild, 'Child ' + convert(nvarchar(2), @idChild), 1);
   set @idChild = @idChild + 1
end

Hibernate テスト コード:

System.Diagnostics.Debug.WriteLine("Test NHibernate:");

Configuration configuration = new Configuration();
configuration.Configure();
configuration.AddAssembly(typeof(Parent).Assembly);

ISessionFactory sessionFactory = configuration.BuildSessionFactory();

Parent parent0, parent1;
using (ISession session = sessionFactory.OpenSession())
{
    using (ITransaction transaction = session.BeginTransaction())
    {
        parent0 = session.Load<Parent>(0);
        parent1 = session.Load<Parent>(1);
        System.Diagnostics.Debug.WriteLine("Before modifications and commit");
        System.Diagnostics.Debug.WriteLine("Parent0 number of children: " + parent0.Children.Count);
        System.Diagnostics.Debug.WriteLine("Parent1 number of children: " + parent1.Children.Count);

        parent0.Children[0].Parent = parent1;

        transaction.Commit();
    }
}
System.Diagnostics.Debug.WriteLine("After modifications and commit");
System.Diagnostics.Debug.WriteLine("Parent0 number of children: " + parent0.Children.Count);
System.Diagnostics.Debug.WriteLine("Parent1 number of children: " + parent1.Children.Count);

エンティティ フレームワークのテスト コード:

System.Diagnostics.Debug.WriteLine("Test Entity Framework:");

Parent parent0, parent1;
using (Entities entities = new Entities())
{
    parent0 = entities.Parents.Find(0);
    parent1 = entities.Parents.Find(1);
    System.Diagnostics.Debug.WriteLine("Before modifications and commit");
    System.Diagnostics.Debug.WriteLine("Parent0 number of children: " + parent0.Children.Count);
    System.Diagnostics.Debug.WriteLine("Parent1 number of children: " + parent1.Children.Count);
    parent0.Children[0].Parent = parent1;

    entities.SaveChanges();
}
System.Diagnostics.Debug.WriteLine("After modifications and commit");
System.Diagnostics.Debug.WriteLine("Parent0 number of children: " + parent0.Children.Count);
System.Diagnostics.Debug.WriteLine("Parent1 number of children: " + parent1.Children.Count);

したがって、基本的にこのテストでは、NHibernate ではなく EF でカウントが変化することがわかります。NH に何か問題がありますか? それとも、変更によって影響を受ける関係のすべての部分を手動で管理する必要がありますか? ありがとう!

4

1 に答える 1

3

Hibernate では、ある親コレクションから別の親コレクションに手動で移動する必要があります。私は通常、親クラスで Add メソッドまたは Remove メソッドを使用してこれを行います。これらの追加または削除メソッドの例を次に示します。

    public virtual void AddLine(OrderLine orderLine)
    {
        orderLine.Order = this;
        this.orderLines.Add(orderLine);
    }

    public virtual void RemoveLine(OrderLine orderLine)
    {
        this.orderLines.Remove(orderLine);
    }

子供の親を変更するには、次のようにします。

    originalParent.RemoveLine(child);

    newParent.AddLine(child);
于 2012-11-06T15:40:31.207 に答える