0

我正在尝试在本地使用 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 的新手,所以这个类在很多方面可能不是最理想的。)

当我尝试创建 type 的对象时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();
    }
    // ...
 }

当我开始调试时,我可以在这里打断点。

我在这里做错了什么?

更新:我想也许我已经启动了 dev fabric 和 ASP.NET localhost,所以我把它们都杀了,启动了 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:我尝试将“Setup CloudStorageAccount Configuration Setting Publisher”区域放在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 的想法有关?

啊。我开始怀念 Google App Engine 存储的简单get()界面put()

4

4 回答 4

2

1) 确保在您的 WebRole 设置中配置了“ DataConnectionString ”。

  • 在您的解决方案资源管理器中 --> 在“角色”文件夹下 --> 右键单击​​ | 属性 --> 转到设置选项卡,然后单击“添加设置”。输入名称:“DataConnectionString”;类型:“连接字符串”;值:“ UseDevelopmentStorage=true ”(如果您想调试和使用本地存储)或者如果您计划迁移到 Azure,请输入您的存储帐户详细信息。

2)(在上面的代码中 - 删除 SetConfigurationSettingPublisher 的注释)。您的代码应如下所示:

CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
{
configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
});
var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");

于 2011-07-09T23:59:34.600 回答
1

我可以想到两个原因:

  1. 您使用的是 Azure SDK 1.3,并且必须在 Global.asax.cs Application_Start 中调用 SetConfigurationSettingPublisher;
  2. 您没有将 Startup 项目设置为 *.CloudService 之一。
于 2011-01-21T17:38:29.967 回答
0

如果您仍然遇到问题,请尝试实际选择 Cloud Project 下的 Web 角色并从那里开始调试,当我遇到其他方法问题时,这对我有用。

于 2011-02-17T23:50:53.293 回答
0

有同样的问题,我没有将 Azure 项目作为启动项目。

正如 Muhammad Omar 在他对该问题的评论中提到的那样,也请参阅这个相关问题

于 2013-07-11T09:36:08.833 回答