2

Azure Cloud Service プロジェクトと 1 つの Web ロールを備えた .NET Web ソリューションがあります。フェールオーバーの目的で東海岸と西海岸のデータ/コンピューティング センターに展開し、Powershell MSBuild と Jenkins を使用して展開を自動化するように依頼されました。

問題は、パッケージ化して各展開に公開する前に、Web.config の Sql Azure データベース connectionString を変更する必要があることです。十分に単純に思えます。

Webrole プロパティの [設定] タブを使用すると、「文字列」または「接続文字列」のいずれかのタイプのカスタム構成プロパティを各展開に追加できることは理解していますが、「接続文字列」オプションは BLOB、テーブル、またはキュー ストレージにのみ適用されるようです。 . 「文字列」を使用して Sql Azure 接続文字列型を指定すると、キーと値のペアとして書き出され、Entity Framework とメンバーシップ プロバイダーはそれを見つけられません。

Sql Azure を指すデプロイごとの接続文字列設定を追加する方法はありますか?

ありがとう、

デビッド

4

2 に答える 2

2

エリックの解決策は完全に有効であり、問​​題を解決するための追加の方法を見つけたので、答えを見つけるのに苦労したので、戻ってきてここに載せると思いました.

秘訣は、Entity Framework と asp.net Membership/profile/session などのプロバイダーを取得して、サイトの web.config ファイルではなく Azure サービス構成から直接接続文字列を読み取ることです。

プロバイダーについては、System.Web.Providers.DefaultMembershipProvider クラスを継承するクラスを作成し、Initialize() メソッドをオーバーライドしてから、作成したヘルパー クラスを使用して、RoleEnvironment.GetConfigurationSettingValue(settingName); を使用して接続文字列を取得することができました。Azure サービス構成から読み取る呼び出し。

次に、メンバーシップ プロバイダーに、DefaultMembershipProvider ではなく自分のクラスを使用するように指示します。コードは次のとおりです。

Web.config:

<membership defaultProvider="AzureMembershipProvider">
  <providers>
    <add name="AzureMembershipProvider" type="clientspace.ServiceConfig.AzureMembershipProvider" connectionStringName="ClientspaceDbContext" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
  </providers>

カスタム プロバイダー "AzuremembershipProvider" に注意してください。

AzuremembershipProvider クラス:

public class AzureMembershipProvider : System.Web.Providers.DefaultMembershipProvider
{
    public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
    {         
        string connectionStringName = config["connectionStringName"];

        AzureProvidersHelper.UpdateConnectionString(connectionStringName, AzureProvidersHelper.GetRoleEnvironmentSetting(connectionStringName), 
            AzureProvidersHelper.GetRoleEnvironmentSetting(connectionStringName + "ProviderName"));

        base.Initialize(name, config);
    }
}

ヘルパー クラス AzureProvidersHelper.cs は次のとおりです。

public static class AzureProvidersHelper
{
    internal static string GetRoleEnvironmentSetting(string settingName)
    {
        try
        {
            return RoleEnvironment.GetConfigurationSettingValue(settingName);
        }
        catch
        {
            throw new ConfigurationErrorsException(String.Format("Unable to find setting in ServiceConfiguration.cscfg: {0}", settingName));
        }
    }

    private static void SetConnectionStringsReadOnly(bool isReadOnly)
    {
        var fieldInfo = typeof (ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
        if (
            fieldInfo != null)
            fieldInfo.SetValue(ConfigurationManager.ConnectionStrings, isReadOnly);
    }

    private static readonly object ConnectionStringLock = new object();

    internal static void UpdateConnectionString(string name, string connectionString, string providerName)
    {
        SetConnectionStringsReadOnly(false);

        lock (ConnectionStringLock)
        {
            ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings["name"];
            if (connectionStringSettings != null)
            {
                connectionStringSettings.ConnectionString = connectionString;
                connectionStringSettings.ProviderName = providerName;
            }
            else
            {
                ConfigurationManager.ConnectionStrings.Add(new ConnectionStringSettings(name, connectionString, providerName));
            }
        }

        SetConnectionStringsReadOnly(true);
    }
}

ここで重要なのは、RoleEnvironment.GetConfigurationSettingValue が web.config ではなく Azure サービス構成から読み取ることです。

プロバイダーを指定しない Entity Framework の場合、ヘルパー クラスの GetRoleEnvironmentSetting() メソッドを使用して、この呼び出しを Global.asax にもう一度追加する必要がありました。

var connString = AzureProvidersHelper.GetRoleEnvironmentSetting("ClientspaceDbContext");

        Database.DefaultConnectionFactory = new SqlConnectionFactory(connString);

このソリューションの良い点は、Azure ロールの onstart イベントを処理する必要がないことです。

楽しみ

ダッシュ

于 2013-05-22T13:16:28.883 に答える
0

デビッド、

適切なオプションは、Azure 構成を使用することです。Azure プロジェクトを右クリックすると、追加の構成を追加できます。接続文字列を正しい構成にします (例: ServiceConfiguration.WestCoast.cscfg、ServiceConfiguration.EastCoast.cscfg など)。

ビルド スクリプトで、TargetProfile プロパティを構成の名前と共に MSBuild に渡すと、それらの設定が最終的な cscfg に組み込まれます。

問題が発生した場合はお知らせください。私はそのアプローチを行いましたが、それを正しく機能させるには数回の試行が必要でした。役立つかもしれないいくつかの詳細

エリック

于 2013-04-16T18:57:42.400 に答える