简体   繁体   English

开发服务器上的Azure出现问题

[英]Trouble with Azure on Development Server

I'm having a bit of trouble making Azure work on the dev server. 使Azure在开发服务器上工作时遇到了一些麻烦。 I have a Silverlight app that I would like to connect to Azure, so I'm exposing a REST API from the Web Role. 我有一个想连接到Azure的Silverlight应用程序,因此我要从Web角色公开REST API。

Here is my service class: 这是我的服务班级:

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ExpenseService
{
    private ExpenseDataSource expenseData = new ExpenseDataSource();

    [OperationContract]
    [WebGet(UriTemplate="expenses", ResponseFormat=WebMessageFormat.Xml)]
    public List<String> GetExpenses()
    {
        return expenseData.Select().ToList();
    }
}

The type initialization of ExpenseDataSource is failing: 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);
    }
    // ...
}

The error is: 错误是:

SEHException was caught SEHException被捕获

External component has thrown an exception. 外部组件引发的异常。

I'm not sure what I'm doing wrong. 我不确定自己在做什么错。 I'm trying to follow along with this tutorial . 我正在尝试按照本教程进行操作 The author describes needing to do something differently for non-Azure environments, like NUnit tests. 作者描述了需要针对非Azure环境(例如NUnit测试)做一些不同的事情。 Do I need to do something for running on the dev server? 我是否需要做一些事情才能在开发服务器上运行? Should I just configure this app to use the real Azure storage, even though it's running off my machine? 即使该应用程序正在我的计算机上运行,​​我是否应该将其配置为使用真正的Azure存储?

Update : If I comment out the ExpenseDataSource constructor and just use fake data, the service works fine. 更新 :如果我注释掉ExpenseDataSource构造函数并仅使用伪造数据,则该服务可以正常工作。

Update 2 : @Maupertuis answered that I can't set up the storage account from a static initializer. 更新2 :@Maupertuis回答我无法从静态初始化程序设置存储帐户。 However, this comes directly from a MS Windows Azure code sample: 但是,这直接来自MS Windows Azure代码示例:

public class GuestBookEntryDataSource
{
    private static CloudStorageAccount storageAccount;
    private GuestBookDataContext context;

    static GuestBookEntryDataSource()
    {
        storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");

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

Could this ever work? 这行得通吗?

As I said earlier (aaarg.. SO outage), you can't initialize your Cloud Apps from inside a static constructor, as the static constructor will be called on type initialization. 如前所述(aaarg .. SO中断),您无法从静态构造函数内部初始化Cloud Apps,因为静态构造函数将在类型初始化时调用。 Type initialization doesn't happen when the assembly is loaded, but when your type is used for the first time. 在加载程序集时不会发生类型初始化,而是在第一次使用类型时发生。

you should use create a class which derives from the class RoleEntryPoint. 您应该使用创建一个从类RoleEntryPoint派生的类。 it's OnStart method will be called on Role startup. 在角色启动时将调用它的OnStart方法。

Here is a sample: 这是一个示例:

public class WebRole: RoleEntryPoint
    {
        public override bool OnStart()
            {
            #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();
        }
    }

You shouldn't call SetConfigurationSettingPublisher from a static constructor. 您不应该从静态构造函数中调用SetConfigurationSettingPublisher。 It is not guaranteed to run at all, and if it runs, there is no guarantee neither about when it will run. 不能保证完全运行,如果可以运行,也不能保证何时运行。

If fact, there are guarantees that it will be executed on Type initialization. 如果确实如此,可以保证它将在Type初始化上执行。 It's right before the first time that your class ExpenseDataSource is used. 就在第一次使用类ExpenseDataSource之前。 If you don't use it in your application, the static constructor won't be executed either. 如果您不在应用程序中使用它,则静态构造函数也不会被执行。 As SetConfigurationSettingPublisher must be called before the first request (if I remember well), you will understand that the static constructor isn't really the way to go. 由于必须在第一个请求之前调用SetConfigurationSettingPublisher(如果我没记错的话),因此您将了解静态构造函数并不是真正的解决之道。

You should create a class deriving from RoleEntryPoint, whose OnStart override will always be called by the Azure platform when it starts: 您应该创建一个从RoleEntryPoint派生的类,该类的OnStart覆盖始终在启动时由Azure平台调用:

public class WebRole: RoleEntryPoint
    {
        public override bool OnStart()
        {
            #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();
        }
    }

It's an example, you can put here whatever initialization code is required by your application. 这是一个示例,您可以在此处放置应用程序所需的任何初始化代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM