Nullable "scalar navigation properties" in EF 4.0: Mapping a non-nullable column from a separate database table to a nullable scalar entity property?

StackOverflow https://stackoverflow.com/questions/23137775

質問

Using Entity Framework version 4.0 (or any other version that is compatible with .NET 4.0), I want to map this existing relational database schema:

Relational database schema

to this logical object model:

Logical object model

which I have tried setting up as follows: (I hope the German captions won't be too disorienting.)

Entity FrameworkFoo entity and settings for its B property" title="Entity Framework's mapping details for the `Foo` entity and settings for its `B` property">

Entity Framework gives me this error:

Error 3031: Problem in mapping fragments …: Non-nullable column FooBs.B in table FooBs is mapped to a nullable entity property.

In the logical model, B ought to be nullable. However, in the database, it isn't, because it resides in a separate table. (I like to avoid nullable database columns.) It only becomes nullable when Foos and FooBs are joined (due to the 1:0..1 cardinality).

How can I fix my mapping, without altering either the database schema or the object model?


P.S.: I also tried this EF 6.0 code-first mapping:

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");
    });
}

But this doesn't work either: When reading from the database, EF ignores all records for which there is no sub-record in FooBs; when writing to the database, it attempts to insert NULL into FooBs.B for all Foo that have their B property set to null.

役に立ちましたか?

解決

There is a rather "dirty" solution that should work. It would require some code changing but would leave your Foo entity with field A and B.

Foo class:

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; }
}

And mapped to database class FooB:

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

On side note - it seems like very strange way to add essentially single nullable column to a table, as there is no logical way where FooB could have more than one non-nullable column, that wouldn't result in deleting whole entity on setting columns value to null.

Another option is creating a database view that would behave like you want and map that to entity.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top