EF 4.1 Mapping Problem

谁说我不能喝 提交于 2019-12-03 07:16:19

Because it's naturally a one-to-many relationship (a person must have one father and one mother but can have many sons and daughters) I'd model it like this:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .HasRequired(p => p.Father)
        .WithMany();

    modelBuilder.Entity<Person>()
        .HasRequired(p => p.Mother)
        .WithMany();
}

This will create two required foreign keys in the database table with name Mother_ID and Father_ID by convention.

Edit

If you want to be able to create persons without Mother and Father you can make the relation optional instead of required:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .HasOptional(p => p.Father)
        .WithMany();

    modelBuilder.Entity<Person>()
        .HasOptional(p => p.Mother)
        .WithMany();
}

Then the foreign keys in the database table are nullable.

If you don't like the default column names for your foreign keys (Mother_ID and Father_ID) you can customize the column names in your mapping:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .HasOptional(p => p.Father)
        .WithMany()
        .Map(m => m.MapKey("FatherID"));

    modelBuilder.Entity<Person>()
        .HasOptional(p => p.Mother)
        .WithMany()
        .Map(m => m.MapKey("MotherID"));
}

For anyone else wondering, this apparently can't be done via DataAnnotation attributes, but can only be configured fluently. http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/08bba96a-20b2-4a3c-9e0e-a5475b703dfe

It's a tad weird but you can do this without the modelBuilder gunk like so:

public class RecursiveModel
{
    public long Id { get; set; }
    public string Name { get; set; }

    public RecursiveModel Father { get; set; }
    public RecursiveModel Mother { get; set; }
    public ICollection<RecursiveModel> Children { get; set; }
}

So basically one of these models will have a list of its children, and if for example this is a mother, each of them will have both their Mother_Id and RecursiveModel_Id set to this object. You'll need to explictly wire it up each time, ideally via a helper method like:

    public void AddAsMotherOfChild(RecursiveModel child)
    {
        Children.Add(child);
        child.Mother = this;
    }

    public void AddAsFatherOfChild(RecursiveModel child)
    {
        Children.Add(child);
        child.Father = this;
    }

Not perfect but it does avoid the modelBuilder code that for me at least gets to be sort of brittle and legion over time.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!