外键绑定问题
Foreign Key Binding issue
你好,我有一个联系人列表。
我正在尝试 link 我的联系方式,以便使用正确的 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
Class。如果我能得到帮助建立一个合适的外键。我想那是我的问题。
// 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 }));
不使用外键的工作方法。
联系方式Class
// 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 }));
我假设您有这样的模型:
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; }
}
现在,要实现你想要的场景,你需要在Contact
和Person
之间配置一个一对多的关系。有两种方法可以做到这一点,使用 Data Annotations or using Fluent 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"));
}
}
如您所见,我正在指定一个未在您的联系人 class 中声明的 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; }
}
如果您想使用与联系人中的人相关的 FK class,您可以这样做:
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 }));
你好,我有一个联系人列表。
我正在尝试 link 我的联系方式,以便使用正确的 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
Class。如果我能得到帮助建立一个合适的外键。我想那是我的问题。
// 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 }));
不使用外键的工作方法。
联系方式Class
// 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 }));
我假设您有这样的模型:
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; }
}
现在,要实现你想要的场景,你需要在Contact
和Person
之间配置一个一对多的关系。有两种方法可以做到这一点,使用 Data Annotations or using Fluent 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"));
}
}
如您所见,我正在指定一个未在您的联系人 class 中声明的 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; }
}
如果您想使用与联系人中的人相关的 FK class,您可以这样做:
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 }));