Entity Framework 7 使用 .Net 中的现有数据库 5 MVC 6

Entity Framework 7 With Existing Database in .Net 5 MVC 6

您好,我在使用 Entity Framework 7 MVC 6 中从现有数据库中提取数据时遇到了一些问题。(我已经发布了项目代码 Here)。我已使用正确的连接字符串设置 appsettings.json:

"Data": {
    "DefaultConnection": {
        "ConnectionString": "Data Source=localhost;Initial Catalog=Demo;Integrated Security=True"
}

我有我的自定义上下文:

public class DatabaseContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Customer> Customers { get; set; }
}

两个 Poco 类:

[Table("Customers")]
public class Customer
{
    [Key]
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string EmailAddress { get; set; }
    public DateTime Created { get; set; }
    public DateTime Updated { get; set; }
    public User User { get; set; }
    public bool Active { get; set; }
}

[Table("Users")]
public class User
{
    [Key]
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string EmailAddress { get; set; }
    public DateTime Created { get; set; }
    public DateTime Updated { get; set; }
    public bool Active { get; set; }
}

我正在 startup.cs

中设置服务
public Startup(IHostingEnvironment env)
    {
        // Set up configuration sources.

        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

        if (env.IsDevelopment())
        {
            // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
            builder.AddUserSecrets();

            // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
            builder.AddApplicationInsightsSettings(developerMode: true);
        }

        builder.AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; set; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);

        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<DatabaseContext>(options =>
                options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddMvc();

        // Add application services.

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseApplicationInsightsRequestTelemetry();

        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");

            // For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
            try
            {
                using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
                    .CreateScope())
                {
                    serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
                         .Database.Migrate();
                }
            }
            catch { }
        }

        app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());

        app.UseApplicationInsightsExceptionTelemetry();

        app.UseStaticFiles();

        app.UseIdentity();

        // To configure external authentication please see http://go.microsoft.com/fwlink/?LinkID=532715

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

    // Entry point for the application.
    public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}

我的用户控制器:

[Route("[controller]")]
public class UsersController : Controller
{
    public DatabaseContext _context { get; set; }

    public UsersController(DatabaseContext context)
    {
        _context = context;
    }
    [Route("[action]")]
    public IActionResult Index()
    {
        using (_context)
        {
            List<User> users = _context.Users.ToList();
        }


        return View();
    }
}

当我导航到 Users/index 页面时,列表行中不断出现以下错误:

$异常{"Object reference not set to an instance of an object."}System.NullReferenceException

出于某种原因,它没有从数据库中提取信息。我在 Microsoft SQLServer 2014 中创建它。并且在用户 table 中有数据。我是漏掉了一个步骤还是试图以错误的方式访问数据?

主要问题可以通过使用

来解决
public UsersController([FromServices] DatabaseContext context)
{
    _context = context;
}

而不是

public UsersController(DatabaseContext context)
{
    _context = context;
}

可以使用

[FromServices]
public DatabaseContext _context { get; set; }

但必须删除 构造函数public UsersController(DatabaseContext context)。不推荐最后一种方式,因为RC2放弃了第二种方式。参见 the announcement

以上更改解决了您遇到的第一个问题,但是您使用的数据库和测试数据又产生了一个问题,因为您的 Users 和 [=21= 的 Updated 字段] tables 包含 NULL 个值。因此你必须使用

public DateTime? Updated { get; set; }

而不是

public DateTime Updated { get; set; }

我推荐你的方式是commend

的用法
dnx ef dbcontext scaffold
    "Data Source=localhost;Initial Catalog=Demo;Integrated Security=True"
    EntityFramework.MicrosoftSqlServer --outputDir ..\Bestro\Model --verbose

您可以在主 project.json 存在的同一目录中执行(在 src\JenSolo 中)。为了更好地阅读,我将部分命令包装在新行中。一个人应该把所有的原因放在一起。上面的命令将创建 UsersCustomers classes 而不是 [Table("Users")]User[Table("Customers")]Customer,但是您可以使用代码作为基础并进行所有需要的修改稍后手动。

已更新: 在我看来,以下命令更符合脚手架的生成 classes:

dnx ef dbcontext scaffold
    "Data Source=localhost;Initial Catalog=Demo;Integrated Security=True"
    EntityFramework.MicrosoftSqlServer --outputDir ..\Bestro\Model --verbose
    --targetProject Bestro --dataAnnotations

因为您在主项目 JenSolo 中使用了 Class Library Bestro。您应该从命令行以文件夹 ...\src\JenSolo 作为当前目录执行上述命令。它将在 Class 库项目 (Bestro) 中创建 Model 文件夹。 Model 文件夹将包含许多 *.cs 文件:每个数据库一个文件 table 和一个附加文件 DemoContext.cs,其中包含 class DemoContext 派生自 DbContextDemo 是您使用的数据库的名称)。您应该从 DemoContext.cs 中删除 OnConfiguring 函数,以便能够通过

配置连接字符串
services.AddEntityFramework()
   .AddSqlServer()
   .AddDbContext<DemoContext>(options =>
      options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

in ConfigureServices of Startup.cs of the main project JenSolo.

更新: 从 .NET Core RC2 开始应该使用 dotnet ef dbcontext scaffold 而不是 dnx ef dbcontext scaffold.