【问题标题】:How to use abstract class in Entity Framework Core?如何在 Entity Framework Core 中使用抽象类?
【发布时间】:2021-04-13 23:39:58
【问题描述】:

从 EF Core 开始,我尝试使用抽象类。我了解我无法实例化抽象类,并且缺少部分代码但找不到解决方法。

代码如下:

using System;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using Microsoft.Extensions.Logging;

namespace ProjectTest1 
{
    public abstract class User 
    {
        [Key]
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public bool IsAdmin { get; set; }
    }

    public class Student : User 
    {
        public string Number { get; set; }
    }

    public class Teacher : User 
    {
        public int Salary { get; set; }
    }

    public class Model : DbContext 
    {
        public static readonly ILoggerFactory _loggerFactory = LoggerFactory.Create(builder => {
            builder.AddConsole();
        });

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=project")
                .EnableSensitiveDataLogging()
                .UseLoggerFactory(_loggerFactory);
        }

        public DbSet<User> Users { get; set; }
    }

    class Program 
    {
        static void Main(string[] args) 
        {
            using var model = new Model();
            model.Database.EnsureCreated();

            model.Users.RemoveRange(model.Users);
            model.SaveChanges();

            var guillaume = new Student() 
            {
                FirstName = "guillaume", 
                LastName = "b", 
                Password = "azerty",
                Email = "guillaume@gmail.com", 
                IsAdmin = true,
                Number = "150200"
            };

            var donald = new Teacher() 
            {
                FirstName = "donald", 
                LastName = "c", 
                Password = "azerty",
                Email = "donald@gmail.com", 
                IsAdmin = false, 
                Salary = 35000
            };

            model.Users.AddRange(new User[] { guillaume, donald });
            model.SaveChanges();
        }
    }
}

代码执行产生错误:

System.InvalidOperationException
HResult=0x80131509

Message=无法实例化实体类型“用户”的相应 CLR 类型,并且模型中没有对应于具体 CLR 类型的派生实体类型。

Source=Microsoft.EntityFrameworkCore

堆栈跟踪:

在 Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateClrInheritance(IModel 模型,IEntityType entityType,HashSet1 validEntityTypes) at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateClrInheritance(IModel model, IDiagnosticsLogger1 记录器) 在 Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel 模型,IDiagnosticsLogger1 logger) at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger1 记录器) 在 Microsoft.EntityFrameworkCore.SqlServer.Internal.SqlServerModelValidator.Validate(IModel 模型,IDiagnosticsLogger1 logger) at Microsoft.EntityFrameworkCore.Metadata.Conventions.ValidatingConvention.ProcessModelFinalized(IModel model) at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalized(IModel model) at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalized(IModel model) at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel() at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel() at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies) at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies) at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel() at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model() at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.&lt;&gt;c.&lt;TryAddCoreServices&gt;b__7_3(IServiceProvider p) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite,TArgument 参数) 在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite,RuntimeResolverContext 上下文,ServiceProviderEngineScope serviceProviderEngine,RuntimeResolverLock lockType) 在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite,RuntimeResolverContext 上下文) 在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument 参数) 在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite,RuntimeResolverContext 上下文,ServiceProviderEngineScope serviceProviderEngine,RuntimeResolverLock lockType) 在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite,RuntimeResolverContext 上下文) 在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.&lt;&gt;c__DisplayClass1_0.&lt;RealizeService&gt;b__0(ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure&lt;System.IServiceProvider&gt;.get_Instance() at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure1 访问者) 在 Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 访问器) 在 Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.get_Dependencies() 在 Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureCreated() 在 C:\Users\yamab\Desktop\ProjectTest1\ProjectTest1\Program.cs:line 48 中的 ProjectTest1.Program.Main(String[] args) 处

读到这个tutorial我想我应该做这样的事情

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
                .Map<Studentt>(m => m.Requires("User").HasValue("S"))
                .Map<Teacher>(m => m.Requires("Usre").HasValue("T"));
}

不确定这是我应该做的,也不知道该怎么做?

【问题讨论】:

  • 如果你想要一个“用户”实体,它不能是抽象的。
  • @Fildor 感谢您的回复。为什么在教程中我提到它似乎已经完成,或者我应该如何使用学生和教师扩展用户?
  • User 只能是 abstract 如果它本身不是实体。因此,如果在您的教程中,某些类是抽象的,那么您所做的事情与教程中的不同。
  • 哦,等一下。 ...“每个层次结构的表”...那篇文章来自 2010 年,因此可能指的是实体框架,not EF Core。你在使用 EF Core 吗? AFAIK,其中一些概念在 EF Core 中(与 Entity Framework 不同)尚未得到支持。
  • @Fildor 我会阅读这些资源,谢谢您的帮助

标签: c# entity-framework-core


【解决方案1】:

感谢@Fildor 的帮助并把我指向Entity type hierarchy mapping

解决方案是添加

public DbSet<Student> Students { get; set; }
public DbSet<Teacher> Teachers { get; set; }

完整代码:

using System;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using Microsoft.Extensions.Logging;

namespace ProjectTest1 {

    public abstract class User {
        [Key]
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string Password { get; set; }

        public string Email { get; set; }

        public bool IsAdmin { get; set; }

    }

    public class Student : User {
        public string Number { get; set; }
    }

    public class Teacher : User {
        public int Salary { get; set; }
    }

    public class Model : DbContext {

        public static readonly ILoggerFactory _loggerFactory = LoggerFactory.Create(builder => {
            builder.AddConsole();
        });
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=project")
                .EnableSensitiveDataLogging()
                .UseLoggerFactory(_loggerFactory);
        }

        public DbSet<User> Users { get; set; }
        public DbSet<Student> Students { get; set; }
        public DbSet<Teacher> Teachers { get; set; }
    }

    class Program {
        static void Main(string[] args) {
            using var model = new Model();
            model.Database.EnsureCreated();

            model.Users.RemoveRange(model.Users);
            model.SaveChanges();

            var guillaume = new Student() {
                FirstName = "guillaume", LastName = "b", Password = "azerty",
                Email = "guillaume@gmail.com", IsAdmin = true , Number = "150200"
            };
            var donald = new Teacher() {
                FirstName = "donald", LastName = "c", Password = "azerty",
                Email = "donald@gmail.com", IsAdmin = false, Salary = 35000
            };

            model.Users.AddRange(new User[] { guillaume, donald });
            model.SaveChanges();

        }
    }
}

【讨论】:

    猜你喜欢
    • 2018-10-04
    • 1970-01-01
    • 2016-06-30
    • 2022-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多