【发布时间】:2015-02-13 04:03:29
【问题描述】:
我有一个实体如下:
public class EntityX {
public int Id { get; set; }
...
[ForeignKey("Scheduled By")]
public string ScheduledById { get; set; }
public virtual ApplicationUser ScheduledBy { get; set; }
}
当我尝试向表中插入一个值时,我收到以下错误:
"INSERT 语句与 FOREIGN KEY 约束冲突 “FK_dbo.EntityX_dbo.ApplicationUsers_ScheduledById”。冲突 发生在数据库“DB”、表“dbo.ApplicationUsers”、“Id”列中。 声明已终止。”
首先想到的是 ApplicationUser 表是空的,因为 IdentityUser 表 (AspNetUsers) 包含所有值。但是,它的 TPH 和一个 Discriminator 列填充了 ApplicationUser 表名。
我已验证在数据库中发送时填充了正确的 ID(即它对应于实际的用户 ID),但无法弄清楚为什么会发生这种情况。
提前谢谢你。干杯!
更新:
“预定者”中的空格是错字。它被错误地复制了。实际代码已按照“ScheduledBy”所指出的那样编写。
更新 2:
问题似乎出在某个地方的上下文中。我有两个,一个从 DbContext 扩展的 DataContext 如下:
public class DataContext : DbContext
{
public DbSet<EntityX> EntityXs { get; set; }
...
}
static DataContext()
{
Database.SetInitializer<DataContext> (new CreateInitializer ());
}
public DataContext()
: base("DataContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id);
modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
...
}
还有一个,从 IdentityDbContext 扩展如下:
public class SecurityContext : IdentityDbContext<ApplicationUser>
{
static SecurityContext()
{
Database.SetInitializer<SecurityContext> (new CreateInitializer ());
}
public SecurityContext()
: base("SecurityContext")
{
Database.Initialize(force: true);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>()
.ToTable("AspNetUsers");
modelBuilder.Entity<ApplicationUser>()
.ToTable("AspNetUsers");
modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id);
modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
base.OnModelCreating(modelBuilder);
}
有了这个,配置工作......但我遇到了一个问题,我在 AspNetUserRoles 表中出现了一个额外的 IdentityRole_Id,如本文所述:EF Code First Migration unwanted column IdentityRole_Id。为了解决这个问题,我在这里按照 Hao Kung 的建议:Create ASP.NET Identity tables using SQL script 并以这种方式更改了我的上下文的 OnModelCreating 方法:
数据上下文:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id);
modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
}
还有 SecurityContext...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var user = modelBuilder.Entity<IdentityUser>()
.ToTable("AspNetUsers");
user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
user.Property(u => u.UserName).IsRequired();
modelBuilder.Entity<ApplicationUser>().ToTable("AspNetUsers"); //Needed?
modelBuilder.Entity<IdentityUserRole>()
.HasKey(r => new { r.UserId, r.RoleId })
.ToTable("AspNetUserRoles");
modelBuilder.Entity<IdentityUserLogin>()
.HasKey(l => new { l.UserId, l.LoginProvider, l.ProviderKey })
.ToTable("AspNetUserLogins");
modelBuilder.Entity<IdentityUserClaim>()
.ToTable("AspNetUserClaims");
var role = modelBuilder.Entity<IdentityRole>()
.ToTable("AspNetRoles");
role.Property(r => r.Name).IsRequired();
role.HasMany(r => r.Users).WithRequired().HasForeignKey(ur => ur.RoleId);
}
虽然这样做可以正确构建数据库,但 AspNetUsers 表中的 Discriminator 列填充了“ApplicationUser”作为值,并且 AspNetUserRoles 中没有额外的列,但是任何将用户的 Id 值作为 FK 插入 EntityX 的尝试都会失败。
我完全迷路了。
【问题讨论】:
-
尝试去掉FK属性中导航属性名称的空格-
[ForeignKey("ScheduledBy")] -
对不起,我复制不正确。我的代码准确地说明了您在上面指定的内容。
标签: sql-server entity-framework ef-code-first asp.net-identity