EntityFramework与NHibernate的关系修复 [英] Relationships fixup in EntityFramework vs NHibernate
问题描述
我一直在尝试实体框架4.4,NHibernate 3.3.1.4000和SQL Server,并且我注意到在提交更改时修复关系时有所不同,我想知道最好的做法是什么我做错了。
I have been experimenting with Entity Framework 4.4, NHibernate 3.3.1.4000 and SQL Server and I have noticed a difference when it comes to fixing up the relationships when you commit your changes, and I was wondering what is the best practice or if I'm doing something wrong.
这是我测试的。我有一个经典的父母链接到n儿童。我有2个父母在数据库中每个20个孩子。我加载父母双方,我拿起第一个父母的第一个孩子,并将该孩子分配给第二个父母。我然后提交更改。
Here's what I tested. I have a classic Parent linked to n Children. I have 2 parents in the database with 20 children each. I load both parents, and I take the first child of the first parent and assign that child the second parent. I then commit the changes.
在EF中,保存完毕后,我可以看到两个父母的儿童收藏的计数都已更改,因此它已修复关系。
In EF, after I have saved, I can see that the count for the Children collection of both parents has been altered, so it fixed up the relationships.
然而,当我在NHibernate中做同样的事情时,计数仍然是一样的。
However, when I do the same thing in NHibernate, the counts remain the same.
这是我的代码设置来重现问题。
Here's my code setup to reproduce the issue.
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; }
}
NHibernate父映射:
<?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>
NHibernate子映射:
<?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 DbContext:
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
NHibernate测试代码:
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);
所以基本上通过这个测试,我可以看到计数随EF而改变,但不是NHibernate。我在NH做错什么事情,或者我必须手动管理受到变更影响的每一部分关系?谢谢!
So basically with this test I can see the counts changing with EF but not with NHibernate. Am I doing something wrong with NH or do I have to manually manage every part of the relationships affected by my changes ? Thanks!
推荐答案
在NHibernate中,您需要手动将它们从一个父集合移动到另一个父集合。我通常使用父类中的添加或删除方法来执行此操作。以下是这些添加或删除方法的示例:
In NHibernate you would need to manually move them from one parent collection to another. I usually use Add or Remove methods in the parent classes to do this. Here is an example of these add or remove methods:
public virtual void AddLine(OrderLine orderLine)
{
orderLine.Order = this;
this.orderLines.Add(orderLine);
}
public virtual void RemoveLine(OrderLine orderLine)
{
this.orderLines.Remove(orderLine);
}
要重建一个孩子,我会做这样的事情:
To reparent a child I would then do something like this:
originalParent.RemoveLine(child);
newParent.AddLine(child);
这篇关于EntityFramework与NHibernate的关系修复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!