我正在使用Asp.net Core和EF core设置IdentityServer4的示例。在此过程中,我想将数据合同和数据访问与核心项目分开。为此,我创建了两个相关项目,一个包含DbContext,另一个包含合同。
最终我想让事情变得更复杂,但首先我只想尝试向IdentityUser添加一个相关对象,该对象默认为ApplicationUser,并在涉及Asp.net Identity的默认项目中存储为ApsnetUsers。
为了实现这一点,我创建了一个继承IdentityUser的基础ApplicationUserDto类。我已经将补充对象/表添加到该对象,并通过更新ModelBuilder测试应用程序,最终,所有内容都按预期工作。
现在问题。我的最终目标是两个有两个独立的类,它们都继承ApplicationUserDto,一个用于内部用户,一个用于外部用户。每个人都有自己的补充一对一数据表。为了开始构建这个,我创建了两个类,InternalUserDto和InternalUserProfilePropertiesDto。
ApplicationUserDto类:
namespace SingleSignOn.Identity.DataAccess.Contracts
{
public class ApplicationUserDto: IdentityUser {}
}
InternalUserDto.cs
namespace SingleSignOn.Identity.DataAccess.Contracts
{
public class InternalUserDto : ApplicationUserDto
{
public virtual InternalUserProfilePropertiesDto InternalUserProfilePropertiesDto { get; set; }
public InternalUserDto() { }
}
}
InternalUserProfilePropertiesDto.cs
namespace SingleSignOn.Identity.DataAccess.Contracts.UserProperties
{
public class InternalUserProfilePropertiesDto
{
public int Id { get; set; }
public string EmployeeId { get; set; }
public virtual InternalUserDto InternalUserDto { get; set; }
}
}
当我尝试使用单用户身份验证使用模板应用程序注册核心时使用这些类我遇到了错误
实体类型 'SingleSignOn.Identity.DataAccess.Contracts.InternalUserDto'在 影状态。有效模型需要所有实体类型 对应的CLR类型
运行模型构建器之后。
以下是我认为来自DbContext的OnModelCreating的相关部分:
namespace SingleSignOn.Identity.DataAccess
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder
.HasAnnotation("ProductVersion", "1.0.0-rc3")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
//Snipped
modelBuilder.Entity("SingleSignOn.Identity.DataAccess.Contracts.ApplicationUserDto", b =>
{
b.Property<string>("Id");
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasAnnotation("MaxLength", 256);
b.Property<bool>("EmailConfirmed");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasAnnotation("MaxLength", 256);
b.Property<string>("NormalizedUserName")
.HasAnnotation("MaxLength", 256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasAnnotation("MaxLength", 256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("Users");
});
modelBuilder.Entity("SingleSignOn.Identity.DataAccess.Contracts.InternalUserDto", b => {
b.ToTable("Users");
});
modelBuilder.Entity("SingleSignOn.Identity.DataAccess.Contracts.UserProperties.InternalUserProfilePropertiesDto", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("EmployeeId");
b.HasKey("Id");
});
modelBuilder.Entity<InternalUserDto>()
.HasOne(typeof(InternalUserProfilePropertiesDto).ToString())
.WithOne()
.HasForeignKey(typeof(InternalUserProfilePropertiesDto).ToString(), "UserId")
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
我搜索了shadow-state,发现合并请求将其作为必需的验证进行检查,但我不明白为什么这种类型没有CLR类型。仅使用ApplicationUserDto和配置文件属性,此相同的设置工作正常,但尝试使用继承的类会立即导致错误。关于我做错了什么,阴影状态是什么或为什么我的类型没有CLR类型的任何见解?我可以提供所需的任何其他代码或详细信息。
修改
我似乎已经解决了我自己的问题。我在DbContext中没有将InternalUserDto或InternalUserProfilePropertiesDto作为DbSets。当我添加这些并将HasOne更改为:
.HasOne(a => a.InternalUserProfilePropertiesDto)
现在一切似乎都有效。我仍然觉得令人困惑的是,我从来没有使用原始ApplicationUserDto的DbSets而且我从未遇到过这个问题,所以如果有人对这个问题有任何想法或建议以及我将来如何避免这种陷阱,我仍然感兴趣。