gpt4 book ai didi

c# - 实体类型 'Microsoft.AspNetCore.Identity.IdentityRole' 处于影子状态

转载 作者:太空宇宙 更新时间:2023-11-03 12:14:43 25 4
gpt4 key购买 nike

我一直在研究这个 quickstart example并且一直在尝试了解我可以在多大程度上自定义数据库(我有一个现有的数据库,我一直在尝试复制它)。

我已经设法触发了下面的异常并且无法修复它,部分原因是我不明白消息告诉我的内容。

InvalidOperationException: Entity type 'Microsoft.AspNetCore.Identity.IdentityRole' is in shadow-state. A valid model requires all entity types to have corresponding CLR type.

我的ApplicationDbContext如下:

using IdentityServerWithAspIdAndEF.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;

namespace IdentityServerWithAspIdAndEF.Data
{
public class ApplicationDbContext : IdentityDbContext<User, Role, int>
{
public ApplicationDbContext(
DbContextOptions<ApplicationDbContext> Options
) : base(Options) { }

protected override void OnModelCreating(ModelBuilder ModelBuilder)
{
base.OnModelCreating(ModelBuilder);

// Customisations

// "IdentityServer4AspNetIdentity.Models.ApplicationUser"
ModelBuilder.Entity<User>(B =>
{
B.Property<int>(P => P.Id)
.HasColumnName("AccountId")
.ValueGeneratedOnAdd();

B.Property<string>("ConcurrencyStamp")
.HasMaxLength(512)
.IsConcurrencyToken();

B.Property<string>("Email")
.HasMaxLength(512)
.IsRequired();

B.Property<bool>("EmailConfirmed")
.ValueGeneratedOnAdd();

B.Property<string>("NormalisedEmail")
.HasMaxLength(512)
.IsRequired();

B.Property<string>("NormalisedUserName")
.HasMaxLength(256)
.IsRequired();

B.Property<string>("PasswordHash");

B.Property<string>("SecurityStamp")
.IsRequired();

B.Property<bool>("TwoFactorEnabled")
.ValueGeneratedOnAdd();

B.Property<string>("UserName")
.HasMaxLength(256)
.IsRequired();

B.Property<DateTime>("Registered")
.ValueGeneratedOnAdd();

B.Property<DateTime>("LastVisit")
.IsRequired();

B.HasKey("AccountId");

B.HasIndex("NormalisedEmail")
.HasName("IX_Users_NormalisedEmail");

B.HasIndex("NormalisedUserName")
.IsUnique()
.HasName("IX_Users_NormalisedUserName");

B.ToTable("Users");
});

// "Microsoft.AspNetCore.Identity.IdentityRole"
ModelBuilder.Entity<Role>(B =>
{
B.Property<int>(P => P.Id)
.HasColumnName("RoleId")
.ValueGeneratedOnAdd();

B.Property<string>("ConcurrencyStamp")
.HasMaxLength(512)
.IsConcurrencyToken();

B.Property<string>("Name")
.HasMaxLength(256);

B.Property<string>("NormalisedName")
.HasMaxLength(256);

B.HasKey(P => P.Id);

B.HasIndex("NormalisedName")
.IsUnique()
.HasName("IX_Roles_NormalisedName");

B.ToTable("Roles");
});

// "Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>"
ModelBuilder.Entity<RoleClaim>(B =>
{
B.Property<int>(P => P.Id)
.HasColumnName("ClaimId")
.ValueGeneratedOnAdd();

B.Property<string>("ClaimType")
.HasMaxLength(128);

B.Property<string>("ClaimValue")
.HasMaxLength(128);

B.Property<int>("RoleId")
.IsRequired();

B.HasIndex(P => P.RoleId)
.HasName("IX_RoleClaims_RoleId");

B.HasOne(D => D.Claim)
.WithMany()
.HasForeignKey(P => P.RoleId)
.OnDelete(DeleteBehavior.Cascade);

B.ToTable("RoleClaims");
});

// "Microsoft.AspNetCore.Identity.IdentityUserClaim<string>"
ModelBuilder.Entity<UserClaim>(B =>
{
B.Property<int>(P => P.Id)
.HasColumnName("ClaimId")
.ValueGeneratedOnAdd();

B.Property<string>("ClaimType")
.HasMaxLength(128);

B.Property<string>("ClaimValue")
.HasMaxLength(128);

B.Property<int>(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();

B.HasIndex("AccountId")
.HasName("IX_UserClaims_AccountId");

B.HasOne(D => D.Account)
.WithMany()
.HasForeignKey(P => P.AccountId)
.OnDelete(DeleteBehavior.Cascade);

B.ToTable("UserClaims");
});

// "Microsoft.AspNetCore.Identity.IdentityUserLogin<string>"
ModelBuilder.Entity<Login>(B =>
{
B.Property<int>(P => P.UserId)
.HasColumnName("LoginId")
.ValueGeneratedOnAdd();

B.Property<string>("LoginProvider")
.HasMaxLength(450)
.IsRequired();

B.Property<string>("ProviderKey")
.HasMaxLength(450)
.IsRequired();

B.Property<string>("ProviderDisplayName");

B.Property<int>("AccountId")
.IsRequired();

B.HasIndex("LoginProvider")
.HasName("IX_Logins_LoginProvider");

B.HasIndex("ProviderKey")
.HasName("IX_Logins_ProviderKey");

B.HasIndex("AccountId")
.HasName("IX_Logins_AccountId");

B.HasOne(D => D.Account)
.WithMany()
.HasForeignKey(P => P.AccountId)
.OnDelete(DeleteBehavior.Cascade);

B.ToTable("Logins");
});

// "Microsoft.AspNetCore.Identity.IdentityUserRole<string>"
ModelBuilder.Entity<UserRole>(B =>
{
B.Property<int>(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();

B.Property<int>("RoleId")
.IsRequired();

B.HasIndex("AccountId")
.HasName("IX_RoleMap_AccountId");

B.HasIndex("RoleId")
.HasName("IX_RoleMap_RoleId");

B.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);

B.HasOne(P => P.Account)
.WithMany()
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade);

B.ToTable("RoleMap");
});

// "Microsoft.AspNetCore.Identity.IdentityUserToken<string>"
ModelBuilder.Entity<Token>(B =>
{
B.Property<int>(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();

B.Property<string>("LoginProvider")
.HasMaxLength(128)
.IsRequired();

B.Property<string>("Name")
.HasMaxLength(64);

B.Property<string>("Value");

B.HasOne(P => P.Account)
.WithMany()
.HasForeignKey(P => P.AccountId)
.OnDelete(DeleteBehavior.Cascade);

B.ToTable("UserTokens");
});

// Non-identity extras

/* snipped */
}
}
}

这些DbSet对应的实体如下:

using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;

namespace IdentityServerWithAspIdAndEF.Models
{
public class User : IdentityUser<int>
{
public int AccountId
{
get => base.Id;
set => base.Id = value;
}
public string NormalisedEmail
{
get => base.NormalizedEmail;
set => base.NormalizedEmail = value;
}
public string NormalisedUserName
{
get => base.NormalizedUserName;
set => base.NormalizedUserName = value;
}
public DateTime Registered { get; set; }
public DateTime LastVisit { get; set; }

public AccountDetail UserDetails { get; set; }
public AccountLockout Lockout { get; set; }
public PasswordReset PasswordResetRequested { get; set; }
public Concierge ConciergeAccountFlag { get; set; }
public NotValidated AccountValidatation { get; set; }

public ICollection<UserRole> AssignedRoles { get; set; }
public ICollection<UserClaim> ClaimsCollection { get; set; }
public ICollection<Login> Logins { get; set; }
public ICollection<LoginAttempt> LoginAttempts { get; set; }
public ICollection<Token> TokenCollection { get; set; }

public new int Id => throw new NotImplementedException();
public override string NormalizedEmail => throw new NotImplementedException();
public override string NormalizedUserName => throw new NotImplementedException();
}

public class Role : IdentityRole<int>
{
public int RoleId
{
get => base.Id;
set => base.Id = value;
}
public string NormalisedName
{
get => base.NormalizedName;
set => base.NormalizedName = value;
}

public ICollection<RoleClaim> ClaimsCollection { get; set; }

private new int Id => throw new NotImplementedException();
private new int NormalizedName => throw new NotImplementedException();
}

public class RoleClaim : IdentityRoleClaim<int>
{
public int ClaimId
{
get => base.Id;
set => base.Id = value;
}

public Role Claim { get; set; }

private new int Id => throw new NotImplementedException();
}

public class UserClaim : IdentityUserClaim<int>
{
public int ClaimId
{
get => base.Id;
set => base.Id = value;
}
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}

public User Account { get; set; }

private new int Id => throw new NotImplementedException();
private new int UserId => throw new NotImplementedException();
}

public class Login : IdentityUserLogin<int>
{
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}

public User Account { get; set; }

private new int UserId => throw new NotImplementedException();
}

public class UserRole : IdentityUserRole<int>
{
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}

public User Account { get; set; }

private new int UserId => throw new NotImplementedException();
}

public class Token : IdentityUserToken<int>
{
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}

private new int UserId => throw new NotImplementedException();

public User Account { get; set; }
}
}

我已阅读帖子 "What does it mean for an entity type to be in “shadow state”?""Entity type 'type' is in shadow-state. A valid model requires all entity types to have corresponding CLR type"

documentation来看我认为我可能在某处遗漏或错误引用了 Role 实体,但我不清楚在哪里。

提前致谢!


编辑:

重新阅读影子属性文档,行“按照惯例,影子属性仅在发现关系时创建,但在依赖实体类中未找到外键属性。在这种情况下,影子外部将引入关键属性。”似乎支持我搞砸了实体。

我试图通过将 RoleRoleClaim ModelBuilder 实体声明中的所有属性引用更改为表达式来排除属性名称不匹配的情况,以查看是否硬引用将有所帮助:

// "Microsoft.AspNetCore.Identity.IdentityRole"
ModelBuilder.Entity<Role>(B =>
{
B.Property(P => P.RoleId)
.ValueGeneratedOnAdd();

B.Property(E => E.ConcurrencyStamp)
.HasMaxLength(512)
.IsConcurrencyToken();

B.Property(E => E.Name)
.HasMaxLength(256);

B.Property(E => E.NormalisedName)
.HasMaxLength(256);

B.HasKey(P => P.Id);

B.HasIndex(E => E.NormalisedName)
.IsUnique()
.HasName("IX_Roles_NormalisedName");

B.ToTable("Roles");
});

// "Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>"
ModelBuilder.Entity<RoleClaim>(B =>
{
B.Property(P => P.ClaimId)
.ValueGeneratedOnAdd();

B.Property(E => E.ClaimType)
.HasMaxLength(128);

B.Property(E => E.ClaimValue)
.HasMaxLength(128);

B.Property(E => E.RoleId)
.IsRequired();

B.HasIndex(P => P.RoleId)
.HasName("IX_RoleClaims_RoleId");

B.HasOne(D => D.Claim)
.WithMany()
.HasForeignKey(P => P.RoleId)
.OnDelete(DeleteBehavior.Cascade);

B.ToTable("RoleClaims");
});

但到目前为止还没有运气。

最佳答案

似乎我犯了几个错误,最相关的是我实际上没有在 ApplicationDbContext 示例中为我的 UserRole 对象提供代码;这实际上是错误的来源......

代码仍然引用了原来的IdentityRole模型:

// "Microsoft.AspNetCore.Identity.IdentityUserRole<string>"
ModelBuilder.Entity<UserRole>(E =>
{
E.Property<int>(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();

E.Property<int>("RoleId")
.IsRequired();

E.HasIndex("AccountId")
.HasName("IX_RoleMap_AccountId");

E.HasIndex("RoleId")
.HasName("IX_RoleMap_RoleId");

E.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") // Argh!
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);

E.HasOne(P => P.Account)
.WithMany()
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade);

E.ToTable("RoleMap");
});

这已更新为引用属性,而不是使用魔术字符串来指定字段名称;这突出了我犯的错误。

// "Microsoft.AspNetCore.Identity.IdentityUserRole<string>"
ModelBuilder.Entity<UserRole>(E =>
{
E.Property(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();

E.Property(P => P.RoleId)
.IsRequired();

E.HasIndex(P => P.AccountId)
.HasName("IX_RoleMap_AccountId");

E.HasIndex(P => P.RoleId)
.HasName("IX_RoleMap_RoleId");

E.HasOne(P => P.Role) // 'UserRole' does not contain a definition for 'Role'
.WithMany()
.HasForeignKey(P => P.RoleId)
.OnDelete(DeleteBehavior.Cascade);

E.HasOne(P => P.Account)
.WithMany()
.HasForeignKey(P => P.AccountId)
.OnDelete(DeleteBehavior.Cascade);

E.ToTable("RoleMap");
});

和:

public class UserRole : IdentityUserRole<int>
{
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}

public User Account { get; set; }
public Role Role { get; set; } // Addition
}

此时,通知我 IdentityRole 在影子状态下运行的异常似乎已经消失并被其他人取代。


另外(我不是 100% 确定这是导致我看到的异常的原因)我在 Startup->ConfigureServices 中错误配置了我的 RoleStore。

Services.AddIdentity<User, Role>()
.AddUserStore<CustomerUserStore>()
.AddUserManager<CustomerManager>()
.AddRoleStore<Role>() // Should have been CustomerRoleStore
.AddRoleManager<RoleManager>()
.AddSignInManager<CustomerSignInManager>()
.AddDefaultTokenProviders();

CustomerRoleStore 还需要重写以允许 IdentityServer 在我的自定义之后理解角色,看起来是这样的:

public class CustomerRoleStore
: RoleStore<Role, ApplicationDbContext, int, UserRole, RoleClaim>
{
public CustomerRoleStore(
ApplicationDbContext context,
IdentityErrorDescriber describer = null
) : base(
context,
describer
)
{ }

protected override RoleClaim CreateRoleClaim(Role role, Claim claim)
{
return new RoleClaim
{
RoleId = role.RoleId,
ClaimType = claim.Type,
ClaimValue = claim.Value
};
}
}

关于c# - 实体类型 'Microsoft.AspNetCore.Identity.IdentityRole' 处于影子状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50366754/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com