Entity Framework 6 在第 3 级子表中编码第一个一对多关系
Entity Framework 6 Code first One-to-Many relation in 3rd level child tables
我有 ApplicationUser
table 由 ASP.NET 身份框架创建,我想使用另一个 table 客户 one-to-one relation
。 ApplicationUser
table的PK
是字符串类型的Id
。 Customer
table 有一个 FK
类型的字符串。我不允许更改 ApplicationUser
table 的 Id
类型。但是客户 table 必须有一个 int 类型的身份(自动编号)列。这很好。
然后这个 Customer
table 与 Contact
table 有 one-to-many
关系。
Customer
和 Contact
table 都有唯一标识列 Id
。 Contact
table 有一个 CustomerId
列。如果没有 AspNetUser
table,代码首先使用这些 id
和 CustomerId
列生成 one-to-many
关系。由于 AspNetuser
table 与 Customer
有 one-to-one
关系,因此不使用 CustomerId
。但是代码首先生成自己的字符串键 (Customer_UserId)
来构建这个 one-to-many
关系。
如何使用 Customer
table 列关联 Contact
table 和 CustomerId
列以使用 EF6 代码优先方法映射关系?
完整代码如下:
应用程序用户
public class ApplicationUser : IdentityUser
{
//Navigation properties
public Customer Customer { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
}
客户
public class Customer
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Index(IsUnique = true)]
public int Id { get; set; }
[Key, ForeignKey("ApplicationUser")]
public string UserId { get; set; }
public string BusinessName { get; set; }
//Navigation properties
[ForeignKey("UserId")]
public ApplicationUser ApplicationUser { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
联系
public class Contact
{
public int Id { get; set; }
public int CustomerId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string OfficeLocation { get; set; }
//Navigation properties
[Required]
public Customer Customer { get; set; }
}
ApplicationDbContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(): base("DefaultConnection", throwIfV1Schema: false){}
static ApplicationDbContext()
{
// Set the database intializer which is run once during application start
// This seeds the database with admin user credentials and admin role
Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>()
.HasRequired(u => u.ApplicationUser).WithRequiredDependent(c => c.Customer);
}
public System.Data.Entity.DbSet<WebServer.Models.Customer> Customers { get; set; }
public System.Data.Entity.DbSet<WebServer.Models.Contact> Contacts { get; set; }
}
我发现删除显式外键并删除联系人的 'Customer' 属性 显着改变了架构。
这将删除 Customer_UserId
。
看起来这就是您所追求的行为。
我明白了。 ApplicationUser
和 Customer
table 是 one-to one
所以两个 table 有相同的 PK
(String Id
在 ApplicationUser
和 Customer
中的 String UserId
)。从逻辑上讲,我们可以将这两个 table 视为一个 table 和 PK
类型 string
。
Contact
table 是 Customer
table 的子代。因此Customer
和Contact
之间存在one-to-many
关系。因此 Contact
table 必须有一个 Foreign Key
类型的字符串。所以模型中的 CustomerId
应该是 string
而不是 int
的类型。此外,为了指示代码优先使用此字段,我需要将 [ForeignKey("CustomerId")]
属性添加到 public Customer Customer { get; set; }
属性.
所以新的Contact模型应该是这样的
public class Contact
{
public int Id { get; set; }
public string CustomerId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string OfficeLocation { get; set; }
//Navigation properties
[ForeignKey("CustomerId")]
[Required]
public Customer Customer { get; set; }
}
PS:在我原来的应用程序中,我在这个 table 层次结构中有另一个级别。一个联系人可以有多个地址,所以 Address
table 可以使用类型 int
的 FK
和 Contact
s PK
组成另一个 one-to-many
关系。
我有 ApplicationUser
table 由 ASP.NET 身份框架创建,我想使用另一个 table 客户 one-to-one relation
。 ApplicationUser
table的PK
是字符串类型的Id
。 Customer
table 有一个 FK
类型的字符串。我不允许更改 ApplicationUser
table 的 Id
类型。但是客户 table 必须有一个 int 类型的身份(自动编号)列。这很好。
然后这个 Customer
table 与 Contact
table 有 one-to-many
关系。
Customer
和 Contact
table 都有唯一标识列 Id
。 Contact
table 有一个 CustomerId
列。如果没有 AspNetUser
table,代码首先使用这些 id
和 CustomerId
列生成 one-to-many
关系。由于 AspNetuser
table 与 Customer
有 one-to-one
关系,因此不使用 CustomerId
。但是代码首先生成自己的字符串键 (Customer_UserId)
来构建这个 one-to-many
关系。
如何使用 Customer
table 列关联 Contact
table 和 CustomerId
列以使用 EF6 代码优先方法映射关系?
完整代码如下:
应用程序用户
public class ApplicationUser : IdentityUser
{
//Navigation properties
public Customer Customer { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
}
客户
public class Customer
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Index(IsUnique = true)]
public int Id { get; set; }
[Key, ForeignKey("ApplicationUser")]
public string UserId { get; set; }
public string BusinessName { get; set; }
//Navigation properties
[ForeignKey("UserId")]
public ApplicationUser ApplicationUser { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
联系
public class Contact
{
public int Id { get; set; }
public int CustomerId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string OfficeLocation { get; set; }
//Navigation properties
[Required]
public Customer Customer { get; set; }
}
ApplicationDbContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(): base("DefaultConnection", throwIfV1Schema: false){}
static ApplicationDbContext()
{
// Set the database intializer which is run once during application start
// This seeds the database with admin user credentials and admin role
Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>()
.HasRequired(u => u.ApplicationUser).WithRequiredDependent(c => c.Customer);
}
public System.Data.Entity.DbSet<WebServer.Models.Customer> Customers { get; set; }
public System.Data.Entity.DbSet<WebServer.Models.Contact> Contacts { get; set; }
}
我发现删除显式外键并删除联系人的 'Customer' 属性 显着改变了架构。
这将删除 Customer_UserId
。
看起来这就是您所追求的行为。
我明白了。 ApplicationUser
和 Customer
table 是 one-to one
所以两个 table 有相同的 PK
(String Id
在 ApplicationUser
和 Customer
中的 String UserId
)。从逻辑上讲,我们可以将这两个 table 视为一个 table 和 PK
类型 string
。
Contact
table 是 Customer
table 的子代。因此Customer
和Contact
之间存在one-to-many
关系。因此 Contact
table 必须有一个 Foreign Key
类型的字符串。所以模型中的 CustomerId
应该是 string
而不是 int
的类型。此外,为了指示代码优先使用此字段,我需要将 [ForeignKey("CustomerId")]
属性添加到 public Customer Customer { get; set; }
属性.
所以新的Contact模型应该是这样的
public class Contact
{
public int Id { get; set; }
public string CustomerId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string OfficeLocation { get; set; }
//Navigation properties
[ForeignKey("CustomerId")]
[Required]
public Customer Customer { get; set; }
}
PS:在我原来的应用程序中,我在这个 table 层次结构中有另一个级别。一个联系人可以有多个地址,所以 Address
table 可以使用类型 int
的 FK
和 Contact
s PK
组成另一个 one-to-many
关系。