如何更改作为 one-to-one 关系创建的记录与其自身 Entity Framework 7 (ASP.NET 核心)?
How to change the record created as a one-to-one relation to itself Entity Framework 7 (ASP.NET Core)?
我在项目中使用EntityFramework 7 RC1
ASP.NET 5 MVC 6 RC 1
我不工作转换角色(每个角色都有一个parent)。下面是我正在尝试做的一个简化示例。此代码运行成功,不会导致错误。
var roleDb = roleManager.FindByNameAsync("UserRole").Result;
var searchRoleDb = roleManager.FindByNameAsync("AdminRole").Result;
if (roleDb != null)
{
roleDb.DateEdit = DateTime.Now;
if (searchRoleDb != null)
{
roleDb.Parent = searchRoleDb;
}
context.Entry(roleDb).State = EntityState.Modified;
context.SaveChanges();
}
但是数据库中的ParentId字段仍然为空
public class ApplicationRole : IdentityRole
{
...
public string ParentId { get; set; }
public virtual ApplicationRole Parent { get; set; }
...
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationRole>()
.HasOne(c => c.Parent)
.WithMany()
.HasForeignKey(c => c.ParentId);
}
}
我也成功更改了数据库中的其他数据,以及成功使用数据迁移。
我不能只更改值 ParentId。
这是因为 roleManager 使用的上下文与您用于数据库修改的上下文不同。你应该通过上下文获取角色然后修改它。
var roleDb = context.Set<IdentityRole>().FirstOrDefault(x => x.Name == "UserRole");
var searchRoleDb = context.Set<IdentityRole>().FirstOrDefault(x => x.Name == "AdminRole");
if (roleDb != null)
{
roleDb.DateEdit = DateTime.Now;
context.SaveChanges();
}
正如我在最初的评论中提到的,您应该在更改角色时使用 asp.net Identity RoleManager class,因为您正在使用它来检索角色作为更改的一部分.您可以使用您的上下文来做到这一点 manually/directly 但这实际上绕过了 asp.net 身份。这是使用 RoleManager 执行更新的原始示例的更新版本:
public async Task UpdateRole()
{
var roleDb = await roleManager.FindByNameAsync("UserRole");
var searchRoleDb = await roleManager.FindByNameAsync("AdminRole");
if (roleDb != null)
{
roleDb.DateEdit = DateTime.Now;
if (searchRoleDb != null)
{
roleDb.Parent = searchRoleDb;
}
await roleManager.UpdateAsync(roleDb);
}
}
我还更新了 FindByNameAsync 调用以使用 "await" 而不是“.Result”以避免我提到的潜在死锁问题。但是,要使其正常工作,方法签名必须 return 一个 Task 并包含 "async" 修饰符。如需有关异步内容的帮助,我建议从 here
开始
编辑
根据关于播种的评论,我通常这样播种我的角色:
internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
protected override void Seed(MyDbContext context)
{
SeedRoles(context);
}
private static void SeedRoles(MyDbContext context)
{
var manager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
CreateRoleIfNotExists(manager, "Role1");
CreateRoleIfNotExists(manager, "Role2");
}
private static void CreateRoleIfNotExists(RoleManager<IdentityRole> manager, string role)
{
if (!manager.RoleExists(role)
{
manager.Create(new IdentityRole(role));
}
}
}
您需要使用上下文、用户和角色 class 更新代码,因为我刚刚使用了默认值。
无需显式保存更改,因为这是在调用 Seed() returns/completes 时由 DbContext class 完成的。使用这种方法,没有异步调用,因此您无需担心我提到的任何相关问题。
我在项目中使用EntityFramework 7 RC1
ASP.NET 5 MVC 6 RC 1
我不工作转换角色(每个角色都有一个parent)。下面是我正在尝试做的一个简化示例。此代码运行成功,不会导致错误。
var roleDb = roleManager.FindByNameAsync("UserRole").Result;
var searchRoleDb = roleManager.FindByNameAsync("AdminRole").Result;
if (roleDb != null)
{
roleDb.DateEdit = DateTime.Now;
if (searchRoleDb != null)
{
roleDb.Parent = searchRoleDb;
}
context.Entry(roleDb).State = EntityState.Modified;
context.SaveChanges();
}
但是数据库中的ParentId字段仍然为空
public class ApplicationRole : IdentityRole
{
...
public string ParentId { get; set; }
public virtual ApplicationRole Parent { get; set; }
...
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationRole>()
.HasOne(c => c.Parent)
.WithMany()
.HasForeignKey(c => c.ParentId);
}
}
我也成功更改了数据库中的其他数据,以及成功使用数据迁移。
我不能只更改值 ParentId。
这是因为 roleManager 使用的上下文与您用于数据库修改的上下文不同。你应该通过上下文获取角色然后修改它。
var roleDb = context.Set<IdentityRole>().FirstOrDefault(x => x.Name == "UserRole");
var searchRoleDb = context.Set<IdentityRole>().FirstOrDefault(x => x.Name == "AdminRole");
if (roleDb != null)
{
roleDb.DateEdit = DateTime.Now;
context.SaveChanges();
}
正如我在最初的评论中提到的,您应该在更改角色时使用 asp.net Identity RoleManager class,因为您正在使用它来检索角色作为更改的一部分.您可以使用您的上下文来做到这一点 manually/directly 但这实际上绕过了 asp.net 身份。这是使用 RoleManager 执行更新的原始示例的更新版本:
public async Task UpdateRole()
{
var roleDb = await roleManager.FindByNameAsync("UserRole");
var searchRoleDb = await roleManager.FindByNameAsync("AdminRole");
if (roleDb != null)
{
roleDb.DateEdit = DateTime.Now;
if (searchRoleDb != null)
{
roleDb.Parent = searchRoleDb;
}
await roleManager.UpdateAsync(roleDb);
}
}
我还更新了 FindByNameAsync 调用以使用 "await" 而不是“.Result”以避免我提到的潜在死锁问题。但是,要使其正常工作,方法签名必须 return 一个 Task 并包含 "async" 修饰符。如需有关异步内容的帮助,我建议从 here
开始编辑
根据关于播种的评论,我通常这样播种我的角色:
internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
protected override void Seed(MyDbContext context)
{
SeedRoles(context);
}
private static void SeedRoles(MyDbContext context)
{
var manager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
CreateRoleIfNotExists(manager, "Role1");
CreateRoleIfNotExists(manager, "Role2");
}
private static void CreateRoleIfNotExists(RoleManager<IdentityRole> manager, string role)
{
if (!manager.RoleExists(role)
{
manager.Create(new IdentityRole(role));
}
}
}
您需要使用上下文、用户和角色 class 更新代码,因为我刚刚使用了默认值。
无需显式保存更改,因为这是在调用 Seed() returns/completes 时由 DbContext class 完成的。使用这种方法,没有异步调用,因此您无需担心我提到的任何相关问题。