Nullable"标量导航属性"在EF 4.0中:将不可为空的列从单独的数据库表映射到可空的标量实体属性?

时间:2014-04-17 15:50:50

标签: entity-framework .net-4.0 nullable non-nullable

使用Entity Framework 4.0版(或与.NET 4.0兼容的任何其他版本),我想映射现有的关系数据库模式:

Relational database schema

到这个逻辑对象模型:

Logical object model

我尝试设置如下:(我希望德语字幕不会太迷惑。)

Entity Framework's mapping details for the <code>Foo</code> entity and settings for its <code>B</code> property

实体框架给了我这个错误:

  

错误3031:映射片段时出现问题...:表FooBs.B中的非可空列FooBs被映射到可以为空的实体属性。

在逻辑模型中,B应该可以为空。但是,在数据库中,它不是,因为它驻留在单独的表中。 (我喜欢避免可以为空的数据库列。)只有在FoosFooBs加入时才会变为可为空(由于1:0..1基数)。

如何在不改变数据库架构或对象模型的情况下修复映射?


  

P.S。:我还尝试了这个EF 6.0代码优先映射:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Foo>()
    .HasKey(f => f.Id)
    .Property(f => f.Id).HasColumnName("FooId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    modelBuilder.Entity<Foo>().Map(f => {
        f.Property(_ => _.A);
        f.ToTable("Foos");
    }).Map(f => {
        f.Property(_ => _.B);
        f.ToTable("FooBs");
    });
}
     

但是这也不起作用:当从数据库中读取时,EF忽略FooBs中没有子记录的所有记录;在写入数据库时​​,它会尝试将NULL插入到FooBs.B中,将Foo属性设置为B的所有null

1 个答案:

答案 0 :(得分:3)

有一个相当&#34;脏&#34;解决方案应该工作。这需要更改一些代码,但会使Foo实体保留字段AB

Foo上课:

class Foo {
   [Key]
   public int FooId { get; set; }
   public int A { get; set; }
   [NotMapped]
   public int? B {
      get {
         return FooB == null ? null : FooB.B;
      }
      set {
         if(value == null) {
            FooB = null;
         } else {
            if(FooB == null)
               FooB = new FooB();
            FooB.B = (int)value;
         }
   public virtual FooB FooB{ get; set; }
}

并映射到数据库类FooB

 class FooB {
    [Key, ForeignKey("FooId")]
    public int FooId { get; set; }
    public int B { get; set; }
 }

侧面注意 - 将基本上单个可空列添加到表中似乎是一种非常奇怪的方式,因为FooB没有逻辑方式可以有多个不可为空的列,这样就不会出现这种情况。 t导致在将列值设置为null时删除整个实体。

另一种选择是创建一个行为与您想要的一样的数据库视图,并将其映射到实体。