Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
577 views
in Technique[技术] by (71.8m points)

entity framework - How do I code an optional one-to-one relationship in EF 4.1 code first with lazy loading and the same primary key on both tables?

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...