C# 如何更改作为一对一关系创建的记录本身与Entity Framework 7(ASP.NET Core)的关系?
我在项目中使用了C# 如何更改作为一对一关系创建的记录本身与Entity Framework 7(ASP.NET Core)的关系?,c#,asp.net-core,asp.net-core-mvc,entity-framework-core,C#,Asp.net Core,Asp.net Core Mvc,Entity Framework Core,我在项目中使用了EntityFramework 7 RC1ASP.NET 5 MVC 6 RC 1 我不会改变角色(每个角色都有一个父角色)。下面是我正在尝试做的一个简单示例。此代码成功运行,不会导致错误 var roleDb = roleManager.FindByNameAsync("UserRole").Result; var searchRoleDb = roleManager.FindByNameAsync("AdminR
EntityFramework 7 RC1
ASP.NET 5 MVC 6 RC 1
我不会改变角色(每个角色都有一个父角色)。下面是我正在尝试做的一个简单示例。此代码成功运行,不会导致错误
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);
}
}
公共类应用程序角色:IdentityRole
{
...
公共字符串ParentId{get;set;}
公共虚拟应用程序角色父级{get;set;}
...
}
公共类ApplicationDbContext:IdentityDbContext
{
模型创建时受保护的覆盖无效(ModelBuilder)
{
基于模型创建(生成器);
builder.Entity()
.HasOne(c=>c.Parent)
.有很多
.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();
}
var-roleDb=context.Set().FirstOrDefault(x=>x.Name==“UserRole”);
var searchRoleDb=context.Set().FirstOrDefault(x=>x.Name==“AdminRole”);
if(roleDb!=null)
{
roleDb.DateEdit=DateTime.Now;
SaveChanges();
}
正如我在最初的评论中提到的,在对角色进行更改时,您应该使用asp.net Identity RoleManager类,因为您使用它来检索角色作为更改的一部分。您可以使用上下文手动/直接执行此操作,但这实际上是绕过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);
}
}
我还更新了findbynamesync调用,使用“wait”而不是“.Result”,以避免我提到的潜在死锁问题。但是,要使其工作,方法签名必须返回任务并包含“async”修饰符。对于异步方面的帮助,我建议启动
编辑
根据关于种子设定的评论,我通常会这样设定我的角色:
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));
}
}
}
内部密封类配置:dbmigtorinsconfiguration
{
受保护的覆盖无效种子(MyDbContext上下文)
{
种子角色(上下文);
}
私有静态角色(MyDbContext上下文)
{
var管理者=新角色管理者(新角色存储(上下文));
CreateRoleIfNotExists(经理,“Role1”);
CreateRoleIfNotExists(经理,“Role2”);
}
私有静态void CreateRoleIfNotExists(角色管理器,字符串角色)
{
如果(!manager.RoleExists(角色)
{
创建(新的IdentityRole(角色));
}
}
}
您需要使用您的上下文、用户和角色类更新代码,因为我刚刚使用了默认值
无需显式保存更改,因为这是在调用Seed()时由DbContext类完成的返回/完成。使用这种方法,没有异步调用,因此您不必担心我提到的任何问题。这很可能是因为您通过RoleManager获取角色,然后尝试使用上下文保存更改。使用RoleManager更新角色
wait RoleManager.updateEasync(roleDb)
另外值得指出的是,调用roleManager.FindBynameAAsync的方式可能会导致应用程序死锁。有关详细信息,请参阅和details@lawst是的,我经常遇到这些信息,但到最后我还是不明白。@lawst在部署ASP.NET核心应用程序时,这些代码对我来说很有用。我替换了roleManager
上下文的同步方法。这将防止出现您描述的问题?请告诉我,此代码context.Set().FirstOrDefault(x=>x.Name==“UserRole”);
和此上下文.Roles.FirstOrDefault(x=>x.Name==“UserRole”)之间有什么区别当我给出一个例子时,我使用了这个方法,因为我不知道DbContext是如何设置的。角色可能只是一个getter,返回IdentityRoleUpdateRole
的数据库集,它是类roleseddata
的一部分,并且Startup.cs/Configure(…)中调用的roleseddata
)
这是同步的。我需要调用一个方法来说明RoleSeedData.Initialize(…).Wait()
?或者我应该更改Configure
方法是异步的吗?@Kolya\u Net我已经更新了种子设定的答案。您不需要使用我提供的方法进行任何异步调用。