外键绑定问题

时间:2015-01-06 21:43:47

标签: c# entity-framework

您好我有一个人员列表,其中也有联系人列表。

我试图链接我的联系方式,以便填充正确的Person_Id

实施例

Id    Name    Method    Value      Person_Id  
1     John    Phone    7777777777    2
2     Joan    Phone    8888888888    8
3     Jack    Phone    9999999999    9

目前它显示Person_Id为所有空值,我相信我没有正确创建ContactMethod类。如果我能帮助建立一个合适的外键。我认为这是我的问题。

// Primary Keys -------------------------------------------------------
public int Id { get; set; }

// Associations -------------------------------------------------------    
public virtual Person Person { get; set; }        

// Fields -------------------------------------------------------------
public string Name {get; set;
public string Value { get; set; }

我通过迁移脚本填充信息,这是一个片段

var person = people.Find(x => x.ContactBase_GUID == contactBaseGuid);

contactMethods.AddRange(channels.Select(pair => new { pair, method = reader.Get<string>(pair.Key) })
                        .Where(x => x.method != null)
                        .Select(x => new ContactMethod { Value = x.method, Person = person }));

不使用外键的工作方法。

ContactMethod类

// Associations -------------------------------------------------------
public int? Person_Id { get; set; }

MigrationScript

 var person = people.Find(x => x.ContactBase_GUID == contactBaseGuid);
 contactMethods.AddRange(channels.Select(pair => new { pair, method = reader.Get<string>(pair.Key) })
                        .Where(x => x.method != null)
                        .Select(x => new ContactMethod { Value = x.method, Person = person.Id }));

1 个答案:

答案 0 :(得分:1)

我会假设你有这样的模特:

public class Contact
{
    public int Id { get; set; }

    public virtual Person Person { get; set; }

    public string Name { get; set; }
    public string Value { get; set; }
}

public class Person
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual ICollection<Contact> Contacts { get; set; }
}

现在,要实现所需的方案,您需要在ContactPerson之间配置一对多关系。有两种方法可以使用Data AnnotationsFluent Api。在这种情况下,我将使用Fluent Api。简单的方法是覆盖Context的OnModelCreating方法来配置关系,例如,以这种方式:

public class YourContext : DbContext
{
    //...
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .HasMany(p => p.Contacts)
            .WithRequired(c => c.Person)
            .Map(f => f.MapKey("Person_Id"));
    }
}

如您所见,我指定的是未在您的Contact类中声明的PK,即您想要的方案。现在使用此配置,您可以执行此操作,例如:

Person john=new Person(){Name = "John"};

var contactList = new List<Contact>() {new Contact(){Name = "Phone",Value = "555-444-333",Person = john},
                                       new Contact() { Name = "email", Value = "john@gmail.com",Person = john}};

using (YourContext db = new YourContext())
{
   db.Contacts.AddRange(contactList);
   db.SaveChanges();
}

更新

如果您想使用数据注释进行相同的配置,您的模型将如下所示:

public class Contact
{
    [Key]
    public int Id { get; set; }

    [InverseProperty("Contacts")]
    public virtual Person Person { get; set; }

    public string Name { get; set; }
    public string Value { get; set; }
}

public class Person
{
    [Key]
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual ICollection<Contact> Contacts { get; set; }
}

如果您想在Contact类中使用与Person相关的FK,您可以这样做:

public class Contact
{
    [Key]
    public int Id { get; set; }

    public int? Person_Id { get; set; }

    [ForeignKey("Person_Id"), InverseProperty("Contacts")]
    public virtual Person Person { get; set; }

    public string Name { get; set; }
    public string Value { get; set; }
}

这样您就可以在第二个迁移脚本中直接使用Person_Id FK:

  var person = people.Find(x => x.ContactBase_GUID == contactBaseGuid);
 contactMethods.AddRange(channels.Select(pair => new { pair, method = reader.Get<string>(pair.Key) })
                        .Where(x => x.method != null)
                        .Select(x => new ContactMethod { Value = x.method, Person_Id = person.Id }));