【问题标题】:Reading connection string placed in ASP.NET Core from class library. Database First从类库中读取放置在 ASP.NET Core 中的连接字符串。数据库优先
【发布时间】:2020-01-02 01:53:32
【问题描述】:

项目结构如下:

  • 汽车(ASP.NET Core MVC。这里有一个连接字符串

  • Cars.Persistence(ASP.NET Core 类库。这里我们有 Repository,Database First)

我通过this msdn docs 的以下命令创建了一个模型:

Scaffold-DbContext "Server=PC\SQL2014XP;Database=Cars;Trusted_Connection=True;" 
    Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

到目前为止一切顺利。但是,现在carsContextCars.Persistence - ASP.NET Core 类库中具有硬编码的连接字符串:

public partial class carsContext: DbContext
{
    public carsContext()
    {
    }

    public carsContext(DbContextOptions<carsContext> options)
        : base(options)
    {
    }

    public virtual DbSet<Cars> Cars { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer("Server=PC\SQL2014XP...");// hard coded 
                                                                  // connection string
        }
    }
}

起初,我想在我的类库Cars.Persistence 中创建自己的appsettings.jsonHowever, according to this post it is not advisable to have appsettings.json file in Class Library..

I've read this approach,但是,如果我再次运行这个命令,硬编码的字符串会再次出现:

Scaffold-DbContext "Server=PC\SQL2014XP;Database=Cars;Trusted_Connection=True;" 
        Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

所以我的问题是如何在我的类库Cars.Persistence 中使用连接字符串(位于Cars 项目中)?

更新:

我已注释掉以下代码:

public partial class eshopContext : DbContext
{

     public eshopContext(DbContextOptions<eshopContext> options): base(options)
     {} 

     // public eshopContext(){}        

      /*protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
     {
         if (!optionsBuilder.IsConfigured)
         {
             #warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
             optionsBuilder.UseSqlServer("Server=...");
         }

      }*/

 }

【问题讨论】:

  • 我对 Dapper 和 IDbConnection 类做了类似的事情。由于您使用的是 Core,因此您可以利用 IOptions 接口包装类并在启动时在组合根附近设置连接字符串。我已经有一段时间没有使用实体框架了,所以我的示例可能没有帮助,但你可以在 Github 上查看:github.com/B-Richie/Dapper_DAL
  • 你让它比实际困难十亿倍!
  • @user10728126 你能说我怎么做更简单吗?
  • 你有上面的例子或转到另一个线程:stackoverflow.com/questions/51304432/…
  • 只需使用 Configuration 映射包含连接字符串的 appsettings.json 部分,并在启动时使用 IOptions 在组合根附近设置值。

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


【解决方案1】:

您可以利用 .Net Core Dependency Injection 和开箱即用的功能。您的连接字符串将保留在 Web 项目中,但您可以使用 DB 上下文而无需在类库项目中声明任何连接字符串。我正在分享我现有项目的代码示例。

设置连接字符串

您在启动时引用了连接字符串并添加到服务中。您无需再次定义连接字符串并使用内置 DI 使用 db 上下文。代码可能是这样的!

入门课程

设置您的 SQL 配置。仔细查看 MigrationsAssembly,这是您将引用您的类库项目的地方。

public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration)
{

    // Add DbContext using SQL Server Provider
    services.AddDbContext<PaymentDbContext>(options =>
        options.UseSqlServer(configuration.GetConnectionString("myconnectionstring"), x => x.MigrationsAssembly("Payment.Persistence")));

    return services;
}

上下文类

这个类在你的类库项目中。

public class PaymentDbContext : DbContext
    {
        public PaymentDbContext(DbContextOptions<PaymentDbContext> options)
            : base(options)
        {

        }

        public DbSet<Payments> Payments { get; set; }    


    }    

使用 DI 访问上下文

    private readonly PaymentDbContext _context;


     public PaymentsRepository(PaymentDbContext dbContext)
     {
     _context = dbContext;
    }

【讨论】:

  • 感谢您的回复!我是否需要三个项目 - Net Core MVC、MigrationAssembly(在此处从 Net Core MVC 获取 connString 并将 connString 设置为 RepositoryAssembly?)和 RepositoryAssembly(此处为数据库优先)?
  • 您只需要 2 个项目。 .net 核心 mvc 和类库项目。这是我调用的包含迁移和数据库上下文(db first)的程序集。你的启动类有指向这个类库的迁移汇编方法
  • 谢谢!那么.NET Core MVC 是否应该依赖于class library?你能写下你的项目依赖吗?
  • 看看这个例子。这是我在 github 上的代码github.com/ImranMA/MicroCouriers/tree/master/src/Services/…
  • 寻找支付接口和持久化。忽略休息
【解决方案2】:

您可以在位于 launchSettings.json 的 Cars MVC 项目中使用 Environment Variable。类似"MSSQL_CONN_STR": "Server=PC\2014XP.."

然后在Cars.Persistence类库中你可以像这样访问环境变量

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
 {
    if (!optionsBuilder.IsConfigured)
    {         
     optionsBuilder.UseSqlServer(Environment.GetEnvironmentVariable("MSSQL_CONN_STR");
    }
}

【讨论】:

    【解决方案3】:

    以下是我如何从netcoreapp2.2 读取连接字符串。你可以在here看到我是如何配置的

    我创建了 1 个文件名 appsetting.json 具有这样的结构

    "WebJobSettings": {
            "DBConnectionString": "Data Source=.;Initial Catalog=CMSCore;Integrated Security=True"
        },
    

    然后在我的 Program.cs 中

     public static class Program
            {
                public static IConfigurationRoot Configuration;
    
                public static void Main()
                {
                    var serviceCollection = new ServiceCollection();
                    ConfigureServices(serviceCollection);
    
                    // create service provider
                    var serviceProvider = serviceCollection.BuildServiceProvider();
    
                    // entry to run app
                    //serviceProvider.GetService<WebJob>().Run();
                    serviceProvider.GetService<WebJob>().RunImageProcessQueue();
                }
    
                private static void ConfigureServices(IServiceCollection serviceCollection)
                {
                    var currentDir = Directory.GetCurrentDirectory();
    
                    // build configuration
                    var configuration = new ConfigurationBuilder()
                        .SetBasePath(currentDir)
                        .AddJsonFile("appsettings.json", false)
                        .Build();
                    serviceCollection.AddOptions();
    
                    serviceCollection.Configure<WebJobSettings>(configuration.GetSection("WebJobSettings"));
                    serviceCollection.Configure<QueueSettings>(configuration.GetSection("QueueSettings"));
                    serviceCollection.Configure<AssetSettings>(configuration.GetSection("AssetSettings"));
    
                    // add app
                    serviceCollection.AddTransient<WebJob>();
                }
    

    然后像这样在我的 WebJob.cs 文件中简单地配置模式

    public class WebJob
    {
        private readonly IOptions<WebJobSettings> _webJobSettings;
        private readonly IOptions<QueueSettings> _queueSettings;
        private readonly IOptions<AssetSettings> _assetSettings;
    
        public WebJob(
            IOptions<WebJobSettings> webJobSettings,
            IOptions<QueueSettings> queueSettings,
            IOptions<AssetSettings> assetSettings)
        {
            _webJobSettings = webJobSettings;
            _queueSettings = queueSettings;
            _assetSettings = assetSettings;
        }
    

    【讨论】:

    • 但是您的存储库放在同一个程序集中?我的意思是,ASP.NET Core 是否具有所有数据库实体?
    • ASP.NET Core 拥有所有数据库实体是什么意思?
    • 我的意思是数据库存储在哪里?在哪个项目中 - ASP.NET Core 或类库?
    • 在 asp 中。 net core 当然,但如果你尝试我的方法,你可以在你的类库项目中访问 db
    【解决方案4】:

    this issue开始,脚手架DbContext时添加到DbContext中的连接字符串是默认设置。如果不想显示这么长丑陋的连接字符串,可以改用命名连接字符串。

    this discussion,你可以在Scaffold-DbContext命令中使用-Connection name来获取web应用的appsetting.json中设置的连接字符串

    Scaffold-DbContext -Connection name=DefaultConnection  Microsoft.EntityFrameworkCore.SqlServer -OutputDir DbModels
    
    "ConnectionStrings": {
      "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MVC2_2Db;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
    },
    

    以上代码会在DbContext中生成如下代码

     protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer("name=DefaultConnection");
            }
        }
    

    或者,如果您设置了外部连接字符串,您可以删除硬编码的连接字符串,因为它只会在您忘记设置与数据库的连接时调用。您可以参考 Startup.cs 中添加的代码如下图:

     var connection = @"Server=(localdb)\mssqllocaldb;Database=MVC2_2Db;Trusted_Connection=True;ConnectRetryCount=0";
    
     services.AddDbContext<Cars.Persistence.DbModels.MVC2_2DbContext>(options => options.UseSqlServer(connection));
    

    【讨论】:

      猜你喜欢
      • 2013-02-23
      • 2018-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多