MVC 6 EF7 RC1創建多個dbcontexts

asp.net-core-mvc entity-framework-core

我試圖弄清楚如何在EF7 RC1中創建第二個DB上下文。在過去,我可以使用構造函數:base(“connectionName”)但不再是一個選項,因為它說不能將字符串轉換為System.IServiceProvider。

我的第二個上下文代碼如下:

public class DecAppContext : DbContext
    {

        public DecAppContext()
          //  :base("DefaultConnection")
        {

        }
        public DbSet<VignetteModels> VignetteModels { get; set; }
        public DbSet<VignetteResult> Result { get; set; }
    }
}

在我的config.json中,我指定了連接:

"Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-xxxxx...;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  }

在我的啟動的配置服務部分中,我添加了兩個上下文:

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

applicationDB上下文工作正常,因為我可以創建用戶並登錄而不會出現問題

但是,當我嘗試通過以下方式訪問控制器中的其他上下文時:

private DecAppContext db = new DecAppContext();
var vignette = db.VignetteModels.SingleOrDefault(v => v.CaseId == vid);

我收到錯誤:

沒有配置數據庫提供程序。在設置服務時,通過在DbContext類或AddDbContext方法中覆蓋OnConfiguring來配置數據庫提供程序。

EF7 RC1中具有多個數據庫上下文並訪問它們的任何工作示例都將非常受歡迎。

一般承認的答案

首先,我會向您推薦GitHub上的EntityFramework維基上的文章 。本文介紹了許多定義DbContext ,它引用了appsettings.json 。我個人更喜歡使用[FromServices]屬性的方式。

代碼可以是以下內容:

首先,您使用以下內容定義了appsettings.json

{
  "Data": {
    "ApplicationDbConnectionString": "Server=(localdb)\\mssqllocaldb;Database=ApplicationDb;Trusted_Connection=True;MultipleActiveResultSets=true",
    "DecAppDbConnectionString": "Server=Server=(localdb)\\mssqllocaldb;Database=DecAppDb;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

您在其中定義兩個連接字符串。

DecAppContext秒鐘,您聲明了以DbContext為基類的類DecAppContextApplicationDbContext 。最簡單的形式就是

public class ApplicationDbContext : DbContext
{
}
public class DecAppContext : DbContext
{
}

沒有任何DbSet屬性。

第三步。您使用Microsoft.Extensions.DependencyInjection注入數據庫上下文。要做到這一點,你需要在Startup.cs類似的內容

public class Startup
{
    // property for holding configuration
    public IConfigurationRoot Configuration { get; set; }

    public Startup(IHostingEnvironment env)
    {
        // Set up configuration sources.
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddEnvironmentVariables();
        // save the configuration in Configuration property
        Configuration = builder.Build();
    }

    // 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.AddMvc()
            .AddJsonOptions(options => {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<ApplicationDbContext>(options => {
                options.UseSqlServer(Configuration["Data:ApplicationDbConnectionString"]);
            })
            .AddDbContext<DecAppContext>(options => {
                options.UseSqlServer(Configuration["Data:DecAppDbConnectionString"]);
            });
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        ...
    }
}

Se使用配置"Data:DecAppDbConnectionString""Data:ApplicationDbConnectionString"創建兩個DbContextDecAppContextApplicationDbContext )。

現在我們可以在控制器中使用上下文。例如

[Route("api/[controller]")]
public class UsersController : Controller
{
    [FromServices]
    public ApplicationDbContext ApplicationDbContext { get; set; }

    [FromServices]
    public DecAppContext DecAppContext { get; set; }

    [HttpGet]
    public IEnumerable<object> Get() {
        var returnObject = new List<dynamic>();

        using (var cmd = ApplicationDbContext.Database.GetDbConnection().CreateCommand()) {
            cmd.CommandText = "SELECT Id, FirstName FROM dbo.Users";
            if (cmd.Connection.State != ConnectionState.Open)
                cmd.Connection.Open();

            var retObject = new List<dynamic>();
            using (var dataReader = cmd.ExecuteReader())
            {
                while (dataReader.Read())
                {
                    var dataRow = new ExpandoObject() as IDictionary<string, object>;
                    for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++)
                        dataRow.Add(
                            dataReader.GetName(iFiled),
                            dataReader.IsDBNull(iFiled) ? null : dataReader[iFiled] // use null instead of {}
                        );

                    retObject.Add((ExpandoObject)dataRow);
                }
            }
            return retObject;
        }
    }
}

或使用async / await相同:

[Route("api/[controller]")]
public class UsersController : Controller
{
    [FromServices]
    public ApplicationDbContext ApplicationDbContext { get; set; }

    [FromServices]
    public DecAppContext DecAppContext { get; set; }

    [HttpGet]
    public async IEnumerable<object> Get() {
        var returnObject = new List<dynamic>();

        using (var cmd = ApplicationDbContext.Database.GetDbConnection().CreateCommand()) {
            cmd.CommandText = "SELECT Id, FirstName FROM dbo.Users";
            if (cmd.Connection.State != ConnectionState.Open)
                cmd.Connection.Open();

            var retObject = new List<dynamic>();
            using (var dataReader = await cmd.ExecuteReaderAsync())
            {
                while (await dataReader.ReadAsync())
                {
                    var dataRow = new ExpandoObject() as IDictionary<string, object>;
                    for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++)
                        dataRow.Add(dataReader.GetName(iFiled), dataReader[iFiled]);

                    retObject.Add((ExpandoObject)dataRow);
                }
            }
            return retObject;
        }
    }
}

可以只聲明屬性public ApplicationDbContext ApplicationDbContext { get; set; }與屬性[FromServices]和ASP.NET從在噴射的情況下對其進行初始化ConfigureServices 。以同樣的方式,您可以在需要時使用第二個上下文DecAppContext

上面的代碼示例將在數據庫上下文中執行SELECT Id, FirstName From dbo.Users並返回格式為[{"id":123, "firstName":"Oleg"},{"id":456, "firstName":"Xaxum"}] 。由於在ConfigureServices中使用AddJsonOptions ,因此在序列化期間將自動將IdFirstName的屬性名稱轉換為idfirstName

更新:我必須參考公告 。下一版本的MVC(RC2)將需要更改上面的代碼以使用[FromServices]作為附加參數(例如方法Get() )而不是使用公共屬性[FromServices] public ApplicationDbContext ApplicationDbContext { get; set; } 。需要刪除屬性ApplicationDbContext並向Get()方法添加其他參數: public async IEnumerable<object> Get([FromServices] ApplicationDbContext applicationDbContext) {...} 。這樣的改變很容易完成。請參閱此處以及MVC演示示例中的更改示例:

[Route("api/[controller]")]
public class UsersController : Controller
{
    [HttpGet]
    public async IEnumerable<object> Get(
                     [FromServices] ApplicationDbContext applicationDbContext,
                     [FromServices] DecAppContext decAppContext)
    {
        var returnObject = new List<dynamic>();

        // ...  the same code as before, but using applicationDbContext 
        // and decAppContext parameters instead of ApplicationDbContext
        // and DecAppContext properties
    }


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow