将派生类型映射到EF中的同一个表

时间:2011-10-21 19:26:34

标签: c# entity-framework

以下简单的代码示例说明了相关方案。我有一个Person实体,它只是映射到DB中的Person表。我正在使用默认的实体对象代码生成器。

public partial class Person { ... }

我有一个派生自Person的PersonDetail类,它包含一些GUI所需的额外属性。这些属性都不需要在DB中保留,因此我不想将此类映射到数据库。

public class PersonDetail : Person
{
    public int TheGuiNeedsThisInformation { get; set; }
}

我使用WCF将详细信息类的实例发送到GUI。 我的问题是,如果GUI修改了PersonDetail实例的某些属性,并将其发送回服务器进行更新,我不能简单地将它附加到我的上下文,因为派生类没有映射到任何表(“映射和无法找到EntityType PersonDetail“)的元数据信息。我试图将它映射到与Person类映射相同的表,但是EF会抛出一些关于映射的异常。

我设法通过创建PersonDetail实例的副本来解决此问题,方法是将其属性值复制到新的Person实例,然后将其保存到DB。但是我想避免那些额外的工作。我究竟做错了什么?这不可能吗?在Linq to SQL中,这就像一个魅力,基本上是开箱即用的。

如果这是不可能的,那么建议的方法是使用一些额外的信息来扩展我的实体类,这些信息不必持久化? (显而易见的方法是简单地向部分Person类添加额外的属性。但是,我不想这样做,因为GUI不能确定服务器上是否已经填充了额外的属性。)

更新:感谢您的建议,但我的主要问题仍然是开放的:是否有可能有一个基类和派生类(其中派生类没有任何必须保存到数据库的附加属性)映射到同一个表,以便我可以简单地将派生类型的实例附加到我的上下文并保存它,如果它是基类型的实例?我还不能这样做,我感到很惊讶,因为使用Linq to SQL它只是起作用。

3 个答案:

答案 0 :(得分:1)

您可以使用modelBuilder将属性添加到类中并为实体框架“忽略”它们,看起来就像是在进行代码优化开发。对于那些选项,请看一下modelBuilder =>

    public class Db : DbContext
    {
      public DbSet<MyClass> MyClasses{ get; set; }

      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
        modelBuilder.Entity<MyClass>().Ignore(x => x.MyProperty);
      }
    }

希望这有帮助!

答案 1 :(得分:1)

我不认为继承是对此的正确答案。 'PersonDetail'是一个人是真的吗? 我会选择创建一个PersonDetail类,并在partial类中添加一个指向PersonDetail类实例的属性。

通过检查属性是否为@ = null,您可以检查客户端是否由服务器设置了PersonDetail。

答案 2 :(得分:0)

您是否尝试过使用合成而不是继承?

public class PersonViewModel {
  public Person Person { get; }
  public int? MyViewProperty { get; set; }
  // ...
}

除非有一个非常好的理由,否则我永远不会将该对象转移到您的服务中。对我来说,它看起来只是一个客户端对象。将GUI属性传输到服务器时,无论如何都没有存储在数据库中,有什么意义呢?仅仅get Person并将其发送到服务器进行更新是不够的?