如何从Entity Framework Core

时间:2019-05-07 07:54:00

标签: c# .net-core entity-framework-core

我正在使用Entityframework Core和代码优先方法建立一个新数据库。我已经在下面的代码清单中设置了一个上下文类,并且为数据库表设置了所有必需的类。 现在,我要使用

创建新数据库
using (var context = new MyContext())
{
    context.Database.EnsureCreated();
}

但是我得到一个错误,该连接字符串不能为null。

我的连接字符串在appsettings.json文件中设置,我在项目构建时将其复制到输出目录。

我尝试了几种不同的方法来从appsettings文件中获取连接字符串,但是所有方法都具有相同的结果。在Startup类的Configuration属性中,我可以看到appsettings文件已正确加载,但是当我想使用

获取字符串时
ConnectionString = Configuration["Connectionstrings:MyConnection"];

ConnectionString始终为null。

我的Startup.cs文件中有此文件:

 public class Startup
 {
    public static string ConnectionString { get; private set; }
    public IConfigurationRoot Configuration { get; set; }

    public Startup(IHostingEnvironment _environment)
    {
        Configuration = new ConfigurationBuilder()
                        .SetBasePath(_environment.ContentRootPath)
                        .AddJsonFile("appsettings.json")
                        .Build();
    }

在“配置-方法”中包含以下内容

using (var context = new MyContext())
{
    context.Database.EnsureCreated();
}

在上下文类中,我有以下代码

public class MyContext : DbContext
{
    public MyContext()
    {
    }

    public static string GetConnectionString()
    {
        return Startup.ConnectionString;
    }

protected override void OnConfiguring(DbContextOptionsBuilder _builder)
{
    _builder.UseSqlServer(GetConnectionString());
}

因此,现在,当我启动应用程序时,在OnConfiguring-方法中出现错误,即连接字符串不能为空。

我的appsettings.json文件是

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },

  "Connnectionstrings": {
    "MyConnection": "server=.;database=MyDatabase;trusted_connection=true;MultipleActiveResultSets=True"
  },
}

3 个答案:

答案 0 :(得分:4)

ConnectionString始终为空,因为有错字,请尝试

ConnectionString = Configuration["Connnectionstrings:MyConnection"];

或在appsettings.json中修复名称

答案 1 :(得分:1)

我可以向您展示两个如何通过从appsettings.json加载的强类型Settings类传递连接字符串的选项。对于这两种方式,您只需要将配置设置从默认的ConnnectionStrings移到自定义部分,并完全控制数据库设置并将其传递给您EntityFramework上下文。

您需要在Startup类中进行此操作:

private Settings _settings;
public Startup(IConfiguration configuration, ...)
{
    Configuration = configuration;
    ...
}

public IConfiguration Configuration { get; }
...
public void ConfigureServices(IServiceCollection services)
{
    services
        .AddOptions()
        .Configure<Settings>(Configuration.GetSection("Settings"))
        .AddSingleton(Configuration);

    _settings = Configuration.GetSection(nameof(Settings)).Get<Settings>();

    services.AddTransient<DesignTimeDbContextFactory>();

    services.AddDbContext<MyContext>(options =>
    {
        if (_settings.DatabaseSettings.UseInMemory)
        {
            options.UseInMemoryDatabase("DummyInMemoryDatabase");
        }
        else
        {
            // Option 1
            options.UseSqlServer(_settings.DatabaseSettings.BuildConnectionString());
            // Option 2
            options.UseSqlServer(_settings.ConnectionStrings.MyConnection);
        }
    });
    ...
}

这是相应的appsettings.json文件:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },

  "Settings": {

    // Option 1: move connection strings to custom strong typed Settings class
    "ConnnectionStrings": {
      "MyConnection": "server=.;database=MyDatabase;trusted_connection=true;MultipleActiveResultSets=True"
    },

    // Option 2: store DB settings any custom way you like - also to get via strong typed Settings class
    "DatabaseSettings": {
      "UseInMemory": false,
      "Host": ".",
      "Name": "MyDatabase",
      "User": "qwerty",
      "Password": "@#$%*"
    }
  }
}

强类型的设置类:

/// <summary> Represents settings configured in appsettings.json file </summary>
public class Settings
{
    /// <summary> Option 1: move connection strings to custom strong typed Settings class </summary>
    public Connections ConnectionStrings { get; set; }

    /// <summary> Option 2: store DB settings any custom way you like - also to get via strong typed Settings class </summary>
    public Database DatabaseSettings { get; set; }
}

public class Connections
{
    public string MyConnection { get; set; }
}

public class Database
{
    public bool UseInMemory { get; set; }
    public string Host { get; set; }
    public string Name { get; set; }
    public string User { get; set; }
    public string Password { get; set; }
    public string BuildConnectionString() => $"Server={Host};Database={Name};User Id={User};Password={Password}";
}

以及用于数据库迁移和其他设计时代码生成的辅助类-DesignTimeDbContextFactory

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyContext>
{
    public  MyContext CreateDbContext(string[] args)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(Path.Combine(Directory.GetCurrentDirectory()))
            .AddJsonFile("appsettings.json", optional: false);

        var config = builder.Build();

        var settingsSection = config.GetSection("Settings");
        var settings = new Settings();
        settingsSection.Bind(settings);

        var optionsBuilder = new DbContextOptionsBuilder<MyContext>()
            .UseSqlServer(settings.ConnectionStrings.MyConnection); // or you can use option #2 either

        return new MyContext(optionsBuilder.Options);
    }
}

答案 2 :(得分:0)

以下模板采用了我从asp.net内核中窃取的模式。

appsettings.json

{
  "ConnectionStrings": {
    "MyConnection": "Data Source=WithSqlite",
    "YourConnection": "Server=(localdb)\\mssqllocaldb;Database=WithSqlServer;Trusted_Connection=True"
  }
}

AppDbContext.cs

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
    // DbSet goes here
}

Program.cs

static class Program
{
    private static readonly IConfiguration _configuration;

    static Program()
    {
        _configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .Build();
    }

    private static void ConfigureServices(IServiceCollection isc)
    {
        isc.AddSingleton(_configuration);

        isc.AddDbContext<AppDbContext>(options =>
        {

            options.UseSqlite(_configuration["ConnectionStrings:MyConnection"]);

            //options .UseSqlServer(_configuration.GetConnectionString("YourConnection"));


        });

        isc.AddSingleton<TheApp>();


    }

    public static  ServiceProvider CreateServiceProvider()
    {
        // create service collection
        IServiceCollection isc = new ServiceCollection();
        ConfigureServices(isc);

        // create service provider
        return isc.BuildServiceProvider();
    }

    private static void Main(string[] args)
    {
        // create application instance and run
        using (var scope = CreateServiceProvider().CreateScope())
        {
            scope.ServiceProvider.GetRequiredService<TheApp>().Run();
            // It is said that GetRequiredService is much better than GetService.
        }
    }
}

TheApp.cs

class TheApp
{
    private readonly AppDbContext _db;


    public TheApp(AppDbContext db)
    {
        _db = db;
    }

    public void Run()
    {

    // Your main logic goes here

    }

}

MigrationHelper.cs

class MigrationHelper: IDesignTimeDbContextFactory<AppDbContext>
{
    public AppDbContext CreateDbContext(string[] args) => 
        Program.CreateServiceProvider()
        .CreateScope()
        .ServiceProvider
        .GetService<AppDbContext>();
}