【问题标题】:EF vs Nhibernate Merge Disconnected Object GraphEF vs Nhibernate 合并断开对象图
【发布时间】:2013-06-19 08:01:44
【问题描述】:

几周前我刚刚开始了一个新项目,并决定尝试 EF Code First, 我之前使用过 NHIbernate,我喜欢 MS 提供的现成 ORM 的想法,到目前为止它一直很棒 - 直到我开始制作复杂的对象。

我的项目层级如下: Azure WCF 角色 - 使用 EF Code First 处理 DAL。 Azure WebSite Role with MVC 4 with Knockout - 处理客户端。 (我为将来需要从不同平台访问服务的情况创建了 WCFRole)

这是我遇到问题的非常基本的 EF Code First 设计: - 我只在服务和站点之间传输 DTO,并制作了一个通用映射器来映射内部 DTO(如果存在)。 - 我有一个 City 表和一个带有 City 属性的 Address 对象(我们需要 City 作为特殊功能的属性,而不仅仅是名称)

客户端知道城市列表,并返回一个包含现有城市的新地址 当我尝试添加新地址时,使用旧现有地址的数据创建了一个新城市,我已经知道会发生这种情况,因为 EF 不知道如何合并断开连接的对象并且我读到的内容不支持任何合并 abitiy,简单的不太舒服的解决方案就是管理对象状态 - 将 City 对象状态更改为 Unchanged。

但是用一个大而复杂的数据库设计来处理这个问题听起来很可怕

我的问题 - 处理此问题的最佳做法/简单方法是什么? 我考虑过解决方案,例如 - 覆盖所有对象的 SaveChanges 方法,如果 ID 不是 null/0/其他约定将其从已添加更改为未更改 - 可以完成此解决方案吗?

我的第二个问题 - 因为我对 NHibernate(连接对象)有很多经验 - 我想知道 NHibernate 对此有何看法?我在某处读到 NHibernate 确实具有 AutoMagic Merge 功能来重新连接断开连接的复杂对象,这是真的吗?我的基本断开连接的地址-> 城市设计将与 AutoMagic 合并一起使用吗? 使用它的后果是什么?

非常感谢:)

更新:问题的简化代码。

public class Address
{
    public int ID { get; set; }

    public virtual City City { get; set; }
}

public class City
{
    public int ID { get; set; }

    public string Name { get; set; }
    public virtual Zone Zone { get; set; }
}

public class MyContext : DbContext
{
    public MyContext() : base("TransportService") { }

    public virtual DbSet<City> Cities { get; set; }
    public virtual DbSet<Address> Addresses { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Address>()
            .HasRequired(x => x.City)
            .WithMany().WillCascadeOnDelete(true);

    }
}

添加新地址:

    public void Add(AddressDto address)
    {
        using (var context = new MyContext())
        {
            context.Addresses.Add(address.FromDto<Address>());

            context.SaveChanges();
        }
    }

“FromDto”是通用 Mapper 扩展,它使用所有信息创建新地址,包括城市(和 City.ID 属性)

这将导致创建一个新城市,而不是使用对旧城市的引用。

【问题讨论】:

  • 如果你展示一些代码来证明你的问题,回答这个问题会容易得多。 EF 可以合并断开的对象,它有一个名为 relationship fixup 的后台进程,但没有代码很难判断这是否对您有帮助。
  • 我给出了基本设计,我将添加代码。
  • 从我读到的关于关系修复的内容中 - 它是手动重新连接,并且仅在当前上下文具有要重新连接的所有对象时才有效。 Nhibernate 具有通过基础 Key 自动合并的功能,此功能在大型复杂对象中节省了很多麻烦,以至于 EF 甚至不是这些项目的候选对象,您只需要 3-4 级内部对象,并开始保持它们与上下文的连接在一个独立的环境中穿在你身上......
  • 好问题!我很想知道答案。到目前为止,我一直在使用 Entity Framework,但是我已经断开了具有 3-4 级内部对象的对象,我完全发现保持它们的连接和关系是一场噩梦!我只是不确定是否值得努力切换到 NHibernate...

标签: c# wcf nhibernate asp.net-mvc-4 entity-framework-5


【解决方案1】:

我发现 EF 没有自动合并功能,目前它们的合并能力只有手动合并,而且只有在 Context 对象在内存中有该对象的所有依赖项时才会起作用。

处理多级断开的对象并手动重新连接它们需要大量工作,并且可能会导致非常奇怪且难以处理的错误(就像问题中所说的那样,新城市是在哪里创建的,因为它不是合并,所以它只是创建了一个新的,即使它有一个 ID)

所以现在 - Nhibernate 赢得了这场战斗, Nhibernate 具有自动合并功能,如果您断开连接的对象有一个 ID,它将尝试合并它,并成功(根据我的经验) 与 EF 相比,它需要更多的设置才能让事情运行起来,但这是值得的。

【讨论】:

  • 我同意。对实体框架来说是多么大的失误。是的,使用 NHibernate 需要一些“调整”才能使事情正确,但是哇,您可以通过 .Merge() 和 B00M 运行它!你完成了。感谢您跟进您的问题...现在我知道我没有疯。
  • 这是一个很好的链接,用于显示“手动跟踪”是如何发生的....此链接用于“断开连接” :::: entityframeworktutorial.net/EntityFramework4.3/…
  • E7 是否会更好地支持断开连接的实体?
猜你喜欢
  • 1970-01-01
  • 2023-03-28
  • 2011-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多