C# 迁移时出现标识和继承错误:无法在';上配置密钥;人';因为它是派生类型
我正在使用EF Core和Identity。 我创建了一个简单的应用程序:C# 迁移时出现标识和继承错误:无法在';上配置密钥;人';因为它是派生类型,c#,asp.net-core,asp.net-identity,entity-framework-core,C#,Asp.net Core,Asp.net Identity,Entity Framework Core,我正在使用EF Core和Identity。 我创建了一个简单的应用程序: public class Program { static void Main(string[] args) { } } public class User : IdentityUser { } public class Person : User { } public class Document { public int Id { get; set; } public
public class Program
{
static void Main(string[] args)
{
}
}
public class User : IdentityUser
{
}
public class Person : User
{
}
public class Document
{
public int Id { get; set; }
public User Owner { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<Person>
{
public DbSet<Person> Person { get; set; }
public DbSet<Document> Document { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=.\;Database=EFCoreDemo;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
公共类程序
{
静态void Main(字符串[]参数)
{
}
}
公共类用户:IdentityUser
{
}
公共类人员:用户
{
}
公共类文档
{
公共int Id{get;set;}
公共用户所有者{get;set;}
}
公共类ApplicationDbContext:IdentityDbContext
{
公共DbSet Person{get;set;}
公共数据库集文档{get;set;}
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
optionsBuilder.UseSqlServer(@“服务器=。\;数据库=EFCoreDemo;可信连接=True;MultipleActiveResultSets=True”);
}
}
当我想添加迁移时,它给了我以下错误:
无法在“Person”上配置密钥,因为它是派生类型。必须在根类型“User”上配置密钥。如果您不希望“用户”包含在模型中,请确保它未包含在上下文的DbSet属性中、未在对ModelBuilder的配置调用中引用或未从模型中包含的类型的导航属性中引用
我已经测试了这些变化:
1) 如果所有者成为Person类型,则会出现错误,但这不是我的选项,因为事实上用户和文档位于库中,我的最终应用程序使用该库,Person位于应用程序中
2) 如果ApplicationDbContext从DbContext继承,则会出现错误
有什么解决办法吗?要使用
Person
和IdentityDbContext
而不更改文档
,您可以从文档
实现一个新模型,并将其更改为Person
public class ApplicationDbContextTest : IdentityDbContext<Person>
{
public DbSet<MyDocument> Document { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCoreDemo;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
public class User : IdentityUser
{
}
public class Person : User
{
}
public class MyDocument:Document
{
public new Person Owner { get; set; }
}
public class Document
{
public int Id { get; set; }
public User Owner { get; set; }
}
公共类ApplicationDbContextTest:IdentityDbContext
{
公共数据库集文档{get;set;}
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
optionsBuilder.UseSqlServer(@“服务器=(localdb)\mssqllocaldb;数据库=EFCoreDemo;受信任的连接=True;MultipleActiveResultSets=True”);
}
}
公共类用户:IdentityUser
{
}
公共类人员:用户
{
}
公共类MyDocument:Document
{
公共新用户所有者{get;set;}
}
公共类文档
{
公共int Id{get;set;}
公共用户所有者{get;set;}
}
要在不更改文档的情况下使用Person
和IdentityDbContext
,您可以从文档
实现一个新模型,并将其更改为Person
public class ApplicationDbContextTest : IdentityDbContext<Person>
{
public DbSet<MyDocument> Document { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCoreDemo;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
public class User : IdentityUser
{
}
public class Person : User
{
}
public class MyDocument:Document
{
public new Person Owner { get; set; }
}
public class Document
{
public int Id { get; set; }
public User Owner { get; set; }
}
公共类ApplicationDbContextTest:IdentityDbContext
{
公共数据库集文档{get;set;}
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
optionsBuilder.UseSqlServer(@“服务器=(localdb)\mssqllocaldb;数据库=EFCoreDemo;受信任的连接=True;MultipleActiveResultSets=True”);
}
}
公共类用户:IdentityUser
{
}
公共类人员:用户
{
}
公共类MyDocument:Document
{
公共新用户所有者{get;set;}
}
公共类文档
{
公共int Id{get;set;}
公共用户所有者{get;set;}
}
为什么从IdentityDbContext继承时会有一个DbSet
呢?@DavidG我已经删除了,但没有效果。也许你可以尝试用外键将用户链接到一个用户,并使这个外键成为个人主键的一部分,因为你的根实体是user
(由于公共用户所有者{get;set;}
的需要,您的上下文应该从IdentityDbContext
派生。最好的解决方案是不要混合上下文。只需将person表添加到业务上下文
中,它有一个链接到当前用户的外键字段(例如基于sub
声明),而不是“真正的”数据库关系。为什么从IdentityDbContext继承时会有DbSet
呢?@DavidG我已经删除了,但没有效果。也许你可以尝试使用外键将用户链接到用户,并将此外键作为根用户主键的一部分如果是User
(因为需要public User Owner{get;set;}
),您的上下文应该从IdentityDbContext
派生。最好的解决方案是不要混合上下文。只需将person表添加到business context
,该表具有链接到当前用户的外键字段(例如,基于sub
claim),而不是一个“真实”的数据库关系。我喜欢你的解决方案,它似乎欺骗了EF,好的事情是当我调用时。包括(d=>d.Owner)它将加载一个人并设置MyDocument.Owner的值。@HamedH如果它有效,您介意接受它作为答案吗?这可以作为简单情况下的解决方案,但缺点是需要为每个模型创建新类,这对于更复杂的情况是不合适的。我目前使用您的解决方案,但不知道它是否可以在没有cla的情况下完成ss MyDocument从基本实体派生时随时引发异常,但在正在构建的EE模型中的某个地方引用了基本类型。我喜欢你的解决方案,它似乎欺骗了EF,好的事情是当我调用时。Include(d=>d.Owner)它将加载一个人并设置MyDocument.Owner的值。@HamedH如果它有效,您介意接受它作为答案吗?这可以作为简单情况下的解决方案,但缺点是需要为每个模型创建新类,这对于更复杂的情况是不合适的。我目前使用您的解决方案,但不知道它是否可以在没有cla的情况下完成ss MyDocument从基本实体派生时,会随时引发异常,但在正在构建的EE模型中的某个位置引用了基本类型。