4

I'm working with an application and data structure built upon ASP/ADO.NET and I'm converting part of it to ASP.NET MVC. In the data structure, there exists a "optional one-to-one" relationship, where both tables use the same primary key, and name. Basically this table can be considered an "optional extension" of the primary table. Here are samples of the model:

public class ZoneMedia
{
    public int ZoneMediaID { get; set; }
    public string MediaName { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }

    public virtual ZoneMediaText MediaText { get; set; }
}

public class ZoneMediaText
{
    public int ZoneMediaID { get; set; }
    public string Text { get; set; }
    public int Color { get; set; }
}

Obviously, EF 4.1 code first has an issue mapping this automatically. So I realize I must specify the mapping explicitly. I tried this:

    modelBuilder.Entity<ZoneMedia>()
        .HasOptional(zm => zm.ZoneMediaText);

    modelBuilder.Entity<ZoneMediaText>()
        .HasRequired(zmt => zmt.ZoneMedia)
        .WithRequiredDependent(zm => zm.ZoneMediaText)
        .Map(m => m.MapKey("ZoneMediaID"));

But it is still giving me an exception about the name of the primary key.

Schema specified is not valid. Errors: 
(199,6) : error 0019: Each property name in a type must be unique. Property name     'ZoneMediaID' was already defined.

I'm a little stumped. I need to adapt to this non-conventional structure I realize in EF 4.1 it would be much easier to just add a unique PK to the optional relation and hold the foreign key relationship in the primary table, but I can't change the database layout. Any advice would be appreciated.

jrummell
  • 42,637
  • 17
  • 112
  • 171
Zack Z.
  • 238
  • 3
  • 10

1 Answers1

6

I hope i understood well.

This works for me:

public class ZoneMedia
{
    public int ZoneMediaID { get; set; }
    public string MediaName { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }

    public virtual ZoneMediaText MediaText { get; set; }
}

public class ZoneMediaText
{
    public int ZoneMediaID { get; set; }
    public string Text { get; set; }
    public int Color { get; set; }

    public virtual ZoneMedia ZoneMedia { get; set; }
}

public class TestEFDbContext : DbContext
{
    public DbSet<ZoneMedia> ZoneMedia { get; set; }
    public DbSet<ZoneMediaText> ZoneMediaText { get; set; }

    protected override void OnModelCreating (DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ZoneMedia>()
            .HasOptional(zm => zm.MediaText);
        modelBuilder.Entity<ZoneMediaText>()
            .HasKey(zmt => zmt.ZoneMediaID);
        modelBuilder.Entity<ZoneMediaText>()
            .HasRequired(zmt => zmt.ZoneMedia)
            .WithRequiredDependent(zm => zm.MediaText);

        base.OnModelCreating(modelBuilder);
    }
}
class Program
{
    static void Main (string[] args)
    {
        var dbcontext = new TestEFDbContext();
        var medias = dbcontext.ZoneMedia.ToList();
    }
}

This Correctly create a FK_ZoneMediaTexts_ZoneMedias_ZoneMediaID in ZomeMediaTexts table, and the Foreign Key is the Primary Key.

EDIT: maybe it's worth pointing out that I'm using EF 4.3.0

WDRust
  • 3,663
  • 1
  • 19
  • 23
  • Yes, this is working. My problem is I was trying to use .Map to define the key when I should have been using the .HasKey method, as illustrated in your example. Thank you for the assistance. – Zack Z. Feb 24 '12 at 18:22
  • According to the MSDN documentation, WithRequiredDependent "Configures the relationship to be required:required with a navigation property on the other side of the relationship" (http://msdn.microsoft.com/en-us/library/gg671273(v=VS.103).aspx). This seems a bit hacky but it does indeed work. Thanks for sharing. – Vinney Kelly Apr 29 '13 at 18:47