web-dev-qa-db-ja.com

ユーザーがログインするときにASP.NET CoreがEF接続文字列を変更する

数時間の調査の後、これを行う方法が見つかりませんでした。質問をする時間です。

複数の顧客が使用しているEF CoreとMVCを使用するASP.NET Core 1.1プロジェクトがあります。各顧客には、まったく同じスキーマを持つ独自のデータベースがあります。このプロジェクトは現在、Webに移行されるWindowsアプリケーションです。ログイン画面には、会社コード、ユーザー名、パスワードの3つのフィールドがあります。ユーザーが会社コード入力に入力した内容に基づいてログインしようとするときに接続文字列を変更できるようにする必要があり、セッション期間中は入力を記憶します。

1つのデータベースと複数のスキーマでこれを行う方法をいくつか見つけましたが、同じスキーマを使用する複数のデータベースではこれを行いませんでした。

この問題を解決した方法は、問題の実際の解決策ではありませんが、回避策がありました。私のデータベースとアプリはAzureでホストされています。これに対する私の修正は、アプリサービスをスロットをサポートするプランにアップグレードすることでした(5スロットで月に20ドルの追加料金のみ)。各スロットには同じプログラムがありますが、接続文字列を保持する環境変数は会社固有です。このようにして、必要に応じて各企業がアクセスするサブドメインにすることもできます。このアプローチは他の人がやることではないかもしれませんが、私にとって最も費用対効果が高いものでした。正しく動作しない他のプログラミングを行う時間を費やすよりも、各スロットに公開する方が簡単です。 Microsoftが接続文字列を簡単に変更できるようになるまで、これが私の解決策です。

ヘルツルの答えに応じて

これはうまくいくようです。私はそれを実装しようとしました。私がやっていることの1つは、自分のコンテキストにアクセスするリポジトリクラスを使用することです。私のコントローラーは、リポジトリーに注入されたリポジトリーを取得して、リポジトリー内のコンテキストにアクセスするメソッドを呼び出します。リポジトリクラスでこれを行うにはどうすればよいですか。リポジトリにはOnActionExecutingオーバーロードはありません。また、これがセッションの間持続する場合、ユーザーがブラウザーをアプリに再度開き、7日間続くCookieを使用して引き続きログインするとどうなりますか?これは新しいセッションではありませんか?セッション変数がnullであり、そのため完全な接続文字列がないため、アプリが例外をスローするように聞こえます。セッション変数がnullの場合、クレームとして保存し、クレームを使用することもできると思います。

これが私のリポジトリクラスです。 IDbContextServiceはProgramContextでしたが、試してみて動作させるための提案を追加し始めました。

public class ProjectRepository : IProjectRepository
{
    private IDbContextService _context;
    private ILogger<ProjectRepository> _logger;
    private UserManager<ApplicationUser> _userManager;

    public ProjectRepository(IDbContextService context,
                            ILogger<ProjectRepository> logger,
                            UserManager<ApplicationUser> userManger)
    {
        _context = context;
        _logger = logger;
        _userManager = userManger;
    }

    public async Task<bool> SaveChangesAsync()
    {
        return (await _context.SaveChangesAsync()) > 0;
    }
}

FORCE JBの回答に応じて

私はあなたのアプローチを実装しようとしました。 Program.csで例外が発生します

Host.Run();

これが私の「Program.cs」クラスです。そのまま。

using System.IO;
using Microsoft.AspNetCore.Hosting;

namespace Project
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var Host = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();

            Host.Run();
        }
    }
}

そして、私の「Startup.cs」クラス。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using Project.Entities;
using Project.Services;

namespace Project
{
    public class Startup
    {
        private IConfigurationRoot _config;

        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json")
                .AddEnvironmentVariables();

            _config = builder.Build();
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton(_config);
            services.AddIdentity<ApplicationUser, IdentityRole>(config =>
            {
                config.User.RequireUniqueEmail = true;
                config.Password.RequireDigit = true;
                config.Password.RequireLowercase = true;
                config.Password.RequireUppercase = true;
                config.Password.RequireNonAlphanumeric = false;
                config.Password.RequiredLength = 8;
                config.Cookies.ApplicationCookie.LoginPath = "/Auth/Login";
                config.Cookies.ApplicationCookie.ExpireTimeSpan = new TimeSpan(7, 0, 0, 0); // Cookies last 7 days
            })
            .AddEntityFrameworkStores<ProjectContext>();
            services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, AppClaimsPrincipalFactory>();
            services.AddScoped<IProjectRepository, ProjectRepository>();
            services.AddTransient<MiscService>();
            services.AddLogging();
            services.AddMvc()
            .AddJsonOptions(config =>
            {
                config.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
        }

        public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
        {
            Dictionary<string, string> connStrs = new Dictionary<string, string>();
            connStrs.Add("company1", "1stconnectionstring"));
            connStrs.Add("company2", "2ndconnectionstring";
            DbContextFactory.SetDConnectionString(connStrs);
            //app.UseDefaultFiles();

            app.UseStaticFiles();
            app.UseIdentity();
            app.UseMvc(config =>
            {
                config.MapRoute(
                    name: "Default",
                    template: "{controller}/{action}/{id?}",
                    defaults: new { controller = "Auth", action = "Login" }
                    );
            });
        }
    }
}

そして例外:

InvalidOperationException: Unable to resolve service for type 'Project.Entities.ProjectContext' while attempting to activate 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`4[Project.Entities.ApplicationUser,Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole,Project.Entities.ProjectContext,System.String]'.

ここで何をすべきかわかりません。

部分的な成功の編集

さて、私はあなたの例を動作させました。別のIDを使用して、リポジトリコンストラクターで接続文字列を設定できます。私の問題は、ログインして適切なデータベースを選択することです。リポジトリが、nullではないものをセッションまたはクレームからプルすることを考えました。ただし、LogInコントローラーでSignInManagerを使用する前に値を設定することはできません。SignInManagerは、セッション変数を更新する前にコンテキストを作成するコントローラーに挿入されるためです。私が考えることができる唯一の方法は、2ページのログインを持つことです。最初のページでは、会社コードを要求し、セッション変数を更新します。 2番目のページではSignInManagerを使用し、リポジトリをコントローラーコンストラクターに挿入します。これは、最初のページがセッション変数を更新した後に発生します。これは、実際には両方のログインビュー間のアニメーションで視覚的に魅力的かもしれません。 2つのログインビューを使用せずにこれを行う方法についてアイデアを持っている人がいない限り、2ページのログインを試みて実装し、機能する場合はコードを投稿します。

実際に壊れています

動作していたのは、有効なCookieがまだあったためです。プロジェクトを実行し、ログインをスキップします。今、私は例外を取得しますInvalidOperationException: No database provider has been configured for this DbContextキャッシュをクリアした後。私はすべてを順を追って説明しましたが、コンテキストは正しく作成されています。私の推測では、Identityには何らかの問題があります。 ConfigureServicesにエンティティフレームワークストアを追加する以下のコードが問題の原因になっている可能性はありますか?

services.AddIdentity<ApplicationUser, IdentityRole>(config =>
{
    config.User.RequireUniqueEmail = true;
    config.Password.RequireDigit = true;
    config.Password.RequireLowercase = true;
    config.Password.RequireUppercase = true;
    config.Password.RequireNonAlphanumeric = false;
    config.Password.RequiredLength = 8;
    config.Cookies.ApplicationCookie.LoginPath = "/Company/Login";
    config.Cookies.ApplicationCookie.ExpireTimeSpan = new TimeSpan(7, 0, 0, 0); // Cookies last 7 days
})
.AddEntityFrameworkStores<ProgramContext>();

編集

Identityが問題であることを確認しました。 PasswordSignInAsyncを実行する前にリポジトリからデータを取得し、データを正常に取得しました。 Identity用のDbContextはどのように作成されますか?

10
ozziwald

DbContextファクトリーを作成する

public static class DbContextFactory
{
    public static Dictionary<string, string> ConnectionStrings { get; set; }

    public static void SetConnectionString(Dictionary<string, string> connStrs)
    {
        ConnectionStrings = connStrs;
    }

    public static MyDbContext Create(string connid)
    {
        if (!string.IsNullOrEmpty(connid))
        {
            var connStr = ConnectionStrings[connid];
            var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
            optionsBuilder.UseSqlServer(connStr);
            return new MyDbContext(optionsBuilder.Options);
        }
        else
        {
            throw new ArgumentNullException("ConnectionId");
        }
    }
}

DbContextファクトリーの初期化

Startup.csで

public void Configure()
{
  Dictionary<string, string> connStrs = new Dictionary<string, string>();
  connStrs.Add("DB1", Configuration["Data:DB1Connection:ConnectionString"]);
  connStrs.Add("DB2", Configuration["Data:DB2Connection:ConnectionString"]);
  DbContextFactory.SetConnectionString(connStrs);
}

使用法

var dbContext= DbContextFactory.Create("DB1");
19
The FORCE JB

あなたの質問によると、私はいくつかのことを想定して解決策を提供します:

最初に、ローカルSQL Serverインスタンスに3つのデータベースを作成しました。

create database CompanyFoo
go

create database CompanyBar
go

create database CompanyZaz
go

次に、各データベースに1行のテーブルを1つ作成します。

use CompanyFoo
go

drop table ConfigurationValue
go

create table ConfigurationValue
(
    Id int not null identity(1, 1),
    Name varchar(255) not null,
    [Desc] varchar(max) not null
)
go

insert into ConfigurationValue values ('Company name', 'Foo Company')
go

use CompanyBar
go

drop table ConfigurationValue
go

create table ConfigurationValue
(
    Id int not null identity(1, 1),
    Name varchar(255) not null,
    [Desc] varchar(max) not null
)
go

insert into ConfigurationValue values ('Company name', 'Bar Company')
go

use CompanyZaz
go

drop table ConfigurationValue
go

create table ConfigurationValue
(
    Id int not null identity(1, 1),
    Name varchar(255) not null,
    [Desc] varchar(max) not null
)
go

insert into ConfigurationValue values ('Company name', 'Zaz Company')
go

次のステップでは、SQL認証を持つユーザーを作成し、データベースを読み取るためのアクセスを許可します。私の場合、ユーザー名はjohndで、パスワードは123です。

これらの手順を完了したら、ASP.NET CoreでMVCアプリケーションを作成します。プロジェクト名としてMultipleCompanyを使用しました。ホームと管理の2つのコントローラーがあります。目標は、最初にログインビューを表示してから別のビューにリダイレクトすることです「ログイン」ビューで選択したデータベースに従ってデータを表示するビュー。

要件を達成するには、ASP.NET Coreアプリケーションでセッションを使用する必要があります。この方法を後でストレージに変更し、後でデータを読み取ることができます。現在のところ、これはコンセプトテスト専用です。

HomeControllerコード:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MultipleCompany.Models;

namespace MultipleCompany.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public IActionResult Index(LoginModel model)
        {
            HttpContext.Session.SetString("CompanyCode", model.CompanyCode);
            HttpContext.Session.SetString("UserName", model.UserName);
            HttpContext.Session.SetString("Password", model.Password);

            return RedirectToAction("Index", "Administration");
        }

        public IActionResult Error()
        {
            return View();
        }
    }
}

AdministrationControllerコード:

using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using MultipleCompany.Models;
using MultipleCompany.Services;

namespace MultipleCompany.Controllers
{
    public class AdministrationController : Controller
    {
        protected IDbContextService DbContextService;
        protected CompanyDbContext DbContext;

        public AdministrationController(IDbContextService dbContextService)
        {
            DbContextService = dbContextService;
        }

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            DbContext = DbContextService.CreateCompanyDbContext(HttpContext.Session.CreateLoginModelFromSession());

            base.OnActionExecuting(context);
        }

        public IActionResult Index()
        {
            var model = DbContext.ConfigurationValue.ToList();

            return View(model);
        }
    }
}

ホームビューのコード:

@{
    ViewData["Title"] = "Home Page";
}

<form action="/home" method="post">
    <fieldset>
        <legend>Log in</legend>

        <div>
            <label for="CompanyCode">Company code</label>
            <select name="CompanyCode">
                <option value="CompanyFoo">Foo</option>
                <option value="CompanyBar">Bar</option>
                <option value="CompanyZaz">Zaz</option>
            </select>
        </div>

        <div>
            <label for="UserName">User name</label>
            <input type="text" name="UserName" />
        </div>

        <div>
            <label for="Password">Password</label>
            <input type="password" name="Password" />
        </div>

        <button type="submit">Log in</button>
    </fieldset>
</form>

管理ビューのコード:

@{
    ViewData["Title"] = "Home Page";
}

<h1>Welcome!</h1>

<table class="table">
    <tr>
        <th>Name</th>
        <th>Desc</th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>@item.Name</td>
            <td>@item.Desc</td>
        </tr>
    }
</table>

LoginModelコード:

using System;
using Microsoft.AspNetCore.Http;

namespace MultipleCompany.Models
{
    public class LoginModel
    {
        public String CompanyCode { get; set; }

        public String UserName { get; set; }

        public String Password { get; set; }
    }

    public static class LoginModelExtensions
    {
        public static LoginModel CreateLoginModelFromSession(this ISession session)
        {
            var companyCode = session.GetString("CompanyCode");
            var userName = session.GetString("UserName");
            var password = session.GetString("Password");

            return new LoginModel
            {
                CompanyCode = companyCode,
                UserName = userName,
                Password = password
            };
        }
    }
}

CompanyDbContextコード:

using System;
using Microsoft.EntityFrameworkCore;

namespace MultipleCompany.Models
{
    public class CompanyDbContext : Microsoft.EntityFrameworkCore.DbContext
    {
        public CompanyDbContext(String connectionString)
        {
            ConnectionString = connectionString;
        }

        public String ConnectionString { get; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(ConnectionString);

            base.OnConfiguring(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }

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

ConfigurationValueコード:

using System;

namespace MultipleCompany.Models
{
    public class ConfigurationValue
    {
        public Int32? Id { get; set; }

        public String Name { get; set; }

        public String Desc { get; set; }
    }
}

AppSettingsコード:

using System;

namespace MultipleCompany.Models
{
    public class AppSettings
    {
        public String CompanyConnectionString { get; set; }
    }
}

IDbContextServiceコード:

using MultipleCompany.Models;

namespace MultipleCompany.Services
{
    public interface IDbContextService
    {
        CompanyDbContext CreateCompanyDbContext(LoginModel model);
    }
}

DbContextServiceコード:

using System;
using Microsoft.Extensions.Options;
using MultipleCompany.Models;

namespace MultipleCompany.Services
{
    public class DbContextService : IDbContextService
    {
        public DbContextService(IOptions<AppSettings> appSettings)
        {
            ConnectionString = appSettings.Value.CompanyConnectionString;
        }

        public String ConnectionString { get; }

        public CompanyDbContext CreateCompanyDbContext(LoginModel model)
        {
            var connectionString = ConnectionString.Replace("{database}", model.CompanyCode).Replace("{user id}", model.UserName).Replace("{password}", model.Password);

            var dbContext = new CompanyDbContext(connectionString);

            return dbContext;
        }
    }
}

起動コード:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MultipleCompany.Models;
using MultipleCompany.Services;

namespace MultipleCompany
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        // 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();

            services.AddEntityFrameworkSqlServer().AddDbContext<CompanyDbContext>();

            services.AddScoped<IDbContextService, DbContextService>();

            services.AddDistributedMemoryCache();
            services.AddSession();

            services.AddOptions();

            services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

            services.AddSingleton<IConfiguration>(Configuration);
        }

        // 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();

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

            app.UseStaticFiles();

            app.UseSession();

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

私のプロジェクトにこのパッケージを追加しました:

"Microsoft.EntityFrameworkCore": "1.0.1",
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
"Microsoft.AspNetCore.Session":  "1.0.0"

私のappsettings.jsonファイル:

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "AppSettings": {
    "CompanyConnectionString": "server=(local);database={database};user id={user id};password={password}"
  }
}

ホームビューで選択したデータベースに接続するという概念に焦点を当ててください。改善としてこのコードの任意の部分を変更できます。簡単な質問に従っていくつかの仮定を立ててこのソリューションを提供していることを忘れないでください、お気軽にお問い合わせください要件に応じてこのコードを改善するための、このソリューションのあらゆる側面について。

基本的に、選択したデータベースに従ってDBコンテキストのインスタンスを作成するサービスを定義する必要があります。それはIDbContextServiceインターフェイスであり、DbContextServiceはそのインターフェイスの実装です。

DbContextServiceコードでわかるように、{}内の値を置き換えて別の接続文字列を作成します。この場合、ドロップダウンリストにデータベース名を追加しましたが、実際の開発ではこの方法は避けてください。データベースおよび他の構成の実際の名前を公開しないようにします。選択したデータベースに従って会社コードを解決するために、コントローラー側からパリティテーブルを作成できます。

このソリューションの改善点の1つは、各値を個別に保存するのではなく、jsonとしてログインモデルをシリアル化するコードを追加することです。

この回答が役立つかどうか教えてください。 PD:完全なコードを1つのドライブにアップロードする場合は、コメントでお知らせください

4
H. Herzl

あなたは答えを見つけましたが、私の投稿は誰かに役立つかもしれません。この質問のような同様の問題がありました。ユーザーがログインした後、別のデータベースサーバーに接続するために、エンティティフレームワークの接続文字列を変更する必要がありました。そして、最初にこの関数をコンテキストクラスから削除しました。

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("your connectionstring...");
            }

外部からこの関数を呼び出せなかったからです。そして、この自動生成されたコンストラクタがありました

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

削除後、このコードをコンテキストクラスに追加しました。

public ClientContext CreateConnectionFromOut(string connectionString)
{
    var optionsBuilder = new DbContextOptionsBuilder<Esdesk_ClientContext>();
    optionsBuilder.UseSqlServer(connectionString);
    var context = new ClientContext(optionsBuilder.Options);
    return context;
}

最後に、接続文字列を好きな場所から変更できます。まさにそのようです

   ClientContext cc = new ClientContext();
   var db = cc.CreateConnectionFromOut("your connection string");

これが誰かのためにうまくいくことを願っています。

1
Emre SOLUĞAN

マルチテナントWebアプリケーションを構築しているため、最初にテナントをどのように区別するかを決定する必要があります。異なるURLを使用する予定ですか?または多分同じURLであるが、URLに一部を追加しますか?

後者を選択したと仮定すると、テナント1のURLは次のようになります。 http:// localhost:9090/tenant1/orders

テナント2のURLは次のようになります。 http:// localhost:9090/tenant2/orders

URLルーティングを使用してこれを行うことができます。

 routes.MapRoute(
                name: "Multitenant",
                url: "{tenant}/{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

接続文字列に関しては、URLに基​​づいて接続文字列を決定し、このクラスをDBコンテキストに挿入するクラスが必要です。

public interface ITenantIdentifier
{
 string GetCurrentTenantId();
}

public class UrlTenantIdentifier : ITenantIdentifier
{
  public string GetCurrentTenantId()
  { 
    //Get the current Http Context and get the URL, you should have a table or configration that maps the URL to the tenant ID and connection string
  }
}

DBコンテキストで:

public class MyDbContext: DbContext
{
 public MyDbContext(ITenantIdentifier tenantIdentifier)
 { 
   var connectionStringName = "TenantConnectionString"+tenantIdentifier.GetCurrentTenantId(); //here assuming that you are following a pattern, each tenant has a connection string in the shape of TenantConnectionString+ID

  var connectionString = //get connection string
  base(connectionString);
 }
}
1
Haitham Shaddad

コンテキストインスタンスの作成中に次のことを試すことができます。

// in class DBHelper
public static YourEntities GetDbContext(string tenantName) 
{
    var connectionStringTemplate =
      @"metadata=res://*/yourModel.csdl|res://*/yourModel.ssdl|res://*/yourModel.msl;" +
      @"provider=System.Data.SqlClient;" +
      @"provider connection string=""data source=.;" +
      @"initial catalog={0};" +
      @"user id=sa;password=pwd;" +
      @"MultipleActiveResultSets=True;App=EntityFramework"";";

     var connectionString = string.Format(connection, tenantName);
     var db = new YourEntities(connectionString);
     return db;
}

次に、パラメータとして文字列を受け取るコンテキストクラスでコンストラクタを作成し、次のように使用します。

var db = DBHelper.GetDbContext(name of database to connect);
0
Awais Mahmood

接続文字列を渡すための更新

動的に生成された接続をコンテキストに渡すには、誰かがカスタムツール(edmxの場合)を実行した場合にコンテキスト部分クラスがそのまま維持されるように、同じコンテキストで部分クラスを作成します。自動生成コードは消去され、再生成されます。部分的なクラスにこのコードがある場合、それは消去されません。最初のコードの場合、これは適用されません。コードは次のとおりです。

public class YourContext : DbContext
{
    public YourContext(string connString)
    {

    }

}

過去にこれを行った方法は、すべてのクライアントのアカウント(ユーザー名、パスワード)が保存されている1つのデータベースを持つことです。アプリケーションが実行されているアカウントは、このデータベースと通信して、ログインしているクライアント(CompanyID、Password)を認証するために使用されます。

その後、認証されると、トークンが生成されます。その後、認証されたユーザーはそのクライアントの(会社の)データベースと対話します。この部分では、次のようにオンザフライで接続を作成できます here ですが、彼女にもコピーして貼り付けます:

// Specify the provider name, server and database.
string providerName = "System.Data.SqlClient";
string serverName = ".";
string databaseName = "AdventureWorks";

// Initialize the connection string builder for the
// underlying provider.
SqlConnectionStringBuilder sqlBuilder =
    new SqlConnectionStringBuilder();

// Set the properties for the data source.
sqlBuilder.DataSource = serverName;
sqlBuilder.InitialCatalog = databaseName;
sqlBuilder.IntegratedSecurity = true;

// Build the SqlConnection connection string.
string providerString = sqlBuilder.ToString();

// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder =
    new EntityConnectionStringBuilder();

//Set the provider name.
entityBuilder.Provider = providerName;

// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;

// Set the Metadata location.
entityBuilder.Metadata = @"res://*/AdventureWorksModel.csdl|
                res://*/AdventureWorksModel.ssdl|
                res://*/AdventureWorksModel.msl";
Console.WriteLine(entityBuilder.ToString());

上記のコードでは、独自のcsdl、ssdl、およびmsl名を提供する必要があります。 Code Firstを使用している場合、接続文字列にメタデータは必要ありません。

0
CodingYoshi