Печаль, Ярость и Отчаяние, настройка хранилища Azure - PullRequest
0 голосов
/ 12 октября 2010

Я пытаюсь использовать хранилище Azure локально.У меня есть класс источника данных с именем ExpenseDataSource:

public class ExpenseDataSource
{
    private static CloudStorageAccount storageAccount;
    private ExpenseTableContext context;

    static ExpenseDataSource()
    {
        //CloudStorageAccount.SetConfigurationSettingPublisher(
        //    (configName, configSettingPublisher) =>
        //    {
        //        string connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
        //        configSettingPublisher(connectionString);
        //    }
        //);

        storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");

        CloudTableClient.CreateTablesFromModel(typeof(ExpenseTableContext), storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
    }

    public ExpenseDataSource()
    {
        context = new ExpenseTableContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
        context.RetryPolicy = RetryPolicies.Retry(3, TimeSpan.FromSeconds(1));
    }

    public IEnumerable<ExpenseInfo> Select()
    {
        var results = from g in context.Expenses
                      where g.PartitionKey == "Expense"
                      select g;

        return results;
    }
    // ...
}

(я новичок в Azure, поэтому этот класс может быть неоптимальным во многих отношениях.)

Когда я пытаюсь создатьобъект типа ExpenseDataSource, возникает следующее исключение:

System.TypeInitializationException: The type initializer for 'WebRole1.ExpenseDataSource' threw an exception. ---> System.InvalidOperationException: SetConfigurationSettingPublisher needs to be called before FromConfigurationSetting can be used
   at Microsoft.WindowsAzure.CloudStorageAccount.FromConfigurationSetting(String settingName)
   at WebRole1.ExpenseDataSource..cctor() in [ ... ]
   --- End of inner exception stack trace ---
   at WebRole1.ExpenseDataSource..ctor()
   at WebRole1.ExpenseService.WebRole1.IExpenseService.GetExpenses() in [ ... ]

Однако это странно, потому что SetConfiguationSettingPublisher уже был вызван:

public class WebRole : RoleEntryPoint
{
    public override bool OnStart()
    {
        DiagnosticMonitor.Start("DiagnosticsConnectionString");

        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
        RoleEnvironment.Changing += RoleEnvironmentChanging;

        CloudStorageAccount.SetConfigurationSettingPublisher(
            (configName, configSettingPublisher) =>
            {
                string connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
                configSettingPublisher(connectionString);
            }
        );

        return base.OnStart();
    }
    // ...
 }

Я могунажмите здесь точки останова, когда я начну отладку.

Что я здесь не так делаю?

Обновление : я подумал, что, возможно, я запустил ткань разработки и ASP.NETlocalhost вышел из строя, поэтому я убил их обоих, запустил dev fabic, затем запустил проект ASP.Все еще не повезло - возникает та же ошибка.

Обновление 2 : я изменил OnStart() на это, но он по-прежнему не работает:

  public override bool OnStart()  
    {
        DiagnosticMonitor.Start("DiagnosticsConnectionString");

        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
        RoleEnvironment.Changing += RoleEnvironmentChanging;

        #region Setup CloudStorageAccount Configuration Setting Publisher

        // This code sets up a handler to update CloudStorageAccount instances when their corresponding
        // configuration settings change in the service configuration file.
        CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
        {
            // Provide the configSetter with the initial value
            configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));

            RoleEnvironment.Changed += (sender, arg) =>
            {
                if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()
                    .Any((change) => (change.ConfigurationSettingName == configName)))
                {
                    // The corresponding configuration setting has changed, propagate the value
                    if (!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)))
                    {
                        // In this case, the change to the storage account credentials in the
                        // service configuration is significant enough that the role needs to be
                        // recycled in order to use the latest settings. (for example, the 
                        // endpoint has changed)
                        RoleEnvironment.RequestRecycle();
                    }
                }
            };
        });
        #endregion

        return base.OnStart();
    }

Обновление 3 : я попытался поместить регион «Настройка издателя настроек конфигурации CloudStorageAccount» в ExpenseDataSource статический инициализатор и получил следующую ошибку:

System.TypeInitializationException: The type initializer for 'WebRole1.ExpenseDataSource' threw an exception. ---> System.Runtime.InteropServices.SEHException: External component has thrown an exception.
   at RoleEnvironmentGetConfigurationSettingValueW(UInt16* , UInt16* , UInt32 , UInt32* )
   at Microsoft.WindowsAzure.ServiceRuntime.Internal.InteropRoleManager.GetConfigurationSetting(String name, String& ret)
   at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue(String configurationSettingName)
   at WebRole1.ExpenseDataSource.<.cctor>b__0(String configName, Func`2 configSetter) in C:\Users\ODP\Documents\Visual Studio 2010\Projects\ExpenseCalc\WebRole1\ExpenseDataSource.cs:line 26
   at Microsoft.WindowsAzure.CloudStorageAccount.StorageAccountConfigurationSetting..ctor(String configurationSettingName)
   at Microsoft.WindowsAzure.CloudStorageAccount.FromConfigurationSetting(String settingName)
   at WebRole1.ExpenseDataSource..cctor() in C:\Users\ODP\Documents\Visual Studio 2010\Projects\ExpenseCalc\WebRole1\ExpenseDataSource.cs:line 47
   --- End of inner exception stack trace ---
   at WebRole1.ExpenseDataSource..ctor()
   at WebRole1.ExpenseService.WebRole1.IExpenseService.GetExpenses() in C:\Users\ODP\Documents\Visual Studio 2010\Projects\ExpenseCalc\WebRole1\ExpenseService.svc.cs:line 18

Обновление 3 : Следуя совету smarx , я изменил статический инициализатор:

    static ExpenseDataSource()
    {
        //storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
        storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"));

        CloudTableClient.CreateTablesFromModel(typeof(ExpenseTableContext), storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
    }

Это приводит к следующей ошибке:

System.TypeInitializationException: The type initializer for 'WebRole1.ExpenseDataSource' threw an exception. ---> System.Runtime.InteropServices.SEHException: External component has thrown an exception.
   at RoleEnvironmentGetConfigurationSettingValueW(UInt16* , UInt16* , UInt32 , UInt32* )
   at Microsoft.WindowsAzure.ServiceRuntime.Internal.InteropRoleManager.GetConfigurationSetting(String name, String& ret)
   at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue(String configurationSettingName)
   at WebRole1.ExpenseDataSource..cctor() in C:\Users\ODP\Documents\Visual Studio 2010\Projects\ExpenseCalc\WebRole1\ExpenseDataSource.cs:line 20
   --- End of inner exception stack trace ---
   at WebRole1.ExpenseDataSource..ctor()
   at WebRole1.ExpenseService.WebRole1.IExpenseService.GetExpenses() in C:\Users\ODP\Documents\Visual Studio 2010\Projects\ExpenseCalc\WebRole1\ExpenseService.svc.cs:line 18

Ошибка незначительнаяотличается от выше.Может ли это быть связано с тем, что я как-то не запускаю ASP.NET внутри dev-ткани?

Тьфу.Я начинаю скучать по простому интерфейсу хранилища Google App Engine get() и put().

Ответы [ 4 ]

2 голосов
/ 10 июля 2011

1) Убедитесь, что « DataConnectionString » настроено в ваших настройках WebRole.

  • В обозревателе решений -> В папке " Roles " -> Щелкните правой кнопкой мыши на | Свойства -> перейдите на вкладку «Настройки» и нажмите «Добавить настройки». Введите Имя: "DataConnectionString"; Тип: " ConnectionString "; Значение: " UseDevelopmentStorage = true " (если вы хотите отлаживать и использовать локальное хранилище) или если вы планируете перейти на Azure, введите данные своей учетной записи хранения.

2) (в приведенном выше коде - удалить комментарий для SetConfigurationSettingPublisher). Ваш код должен выглядеть так:

CloudStorageAccount.SetConfigurationSettingPublisher ((configName, configSetter) =>
{
configSetter (RoleEnvironment.GetConfigurationSettingValue (configName));
}); * * Тысяча двадцать-один var storageAccount = CloudStorageAccount.FromConfigurationSetting ("DataConnectionString");

1 голос
/ 21 января 2011

Я могу думать о двух причинах:

  1. Вы используете Azure SDK 1.3, и SetConfigurationSettingPublisher должен вызываться в вашем Global.asax.cs Application_Start;
  2. Вы не устанавливаете проект запуска как * .CloudService.
0 голосов
/ 11 июля 2013

У меня была такая же проблема, у меня не было проекта Azure в качестве начального проекта.

Как отметил Мухаммед Омар в своем комментарии к этому вопросу, см. Также этот связанный вопрос .

0 голосов
/ 18 февраля 2011

Если у вас все еще есть проблемы, попробуйте выбрать веб-роль в облачном проекте и начать отладку, что сработало для меня, когда у меня возникли проблемы с другими методами.

...