2010-10-09 112 views
2

我在開發服務器上進行Azure工作時遇到了一些麻煩。我有一個我想連接到Azure的Silverlight應用程序,因此我從Web角色公開了一個REST API。開發服務器上的Azure問題

這裏是我的服務類:

[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(); 
    } 
} 

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); 
    } 
    // ... 
} 

的錯誤是:

SEHException被抓獲

外部合作mponent已拋出一個 異常。

我不知道我在做什麼錯。我正在嘗試跟隨此tutorial。作者描述了需要爲非Azure環境做不同的事情,比如NUnit測試。我需要在開發服務器上運行一些東西嗎?我是否應該配置此應用程序以使用真正的Azure存儲,即使它正在運行我的機器?

更新:如果我註釋掉ExpenseDataSource構造,只是用假數據,該服務工作正常。

更新2:@Maupertuis回答說我無法從靜態初始化程序設置存儲帳戶。但是,這直接來自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); 
    } 
    // ... 
} 

難道這能工作嗎?

回答

1

正如前面所述(aaarg .. SO outage),您無法從靜態構造函數中初始化您的Cloud Apps,因爲將在類型初始化時調用靜態構造函數。裝入程序集時不會發生類型初始化,但是第一次使用類型時。

您應該使用創建一個從RoleEntryPoint類派生的類。它的OnStart方法將在角色啓動時調用。

這裏有一個例子:

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(); 
     } 
    } 
+0

是的,SO停電是一個巨大的痛苦。謝謝你的回答,我會試試這個。我認爲這樣做的原因可以從我從MSFT下載的Windows Azure培訓套件(上面貼出)中找到。奇。 – 2010-10-09 16:14:36

+0

我把'SetConfigurationSettingPublisher'調用放在'OnStart()'中,但它永遠不會被調用。我在那裏沒有被擊中的斷點。我認爲'OnStart()'總是跑? – 2010-10-09 16:43:02

+1

WebRole類是公開的嗎?它是否繼承自RoleEntryPoint?它是您的應用唯一的RoleEntryPoint類嗎? – Eilistraee 2010-10-11 10:44:32

0

你不應該從靜態構造函數中調用SetConfigurationSettingPublisher。它不保證運行,如果運行,也不保證運行的時間。

如果實際上有保證它會在類型初始化時執行。在第一次使用類ExpenseDataSource之前。如果你不在應用程序中使用它,靜態構造函數也不會被執行。由於必須在第一個請求之前調用SetConfigurationSettingPublisher(如果我沒記錯的話),你會明白靜態構造函數並不是真正的方法。

,當它啓動時,你應該創建一個類從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(); 
     } 
    } 

這是一個例子,你可以把這裏所要求的任何初始化代碼你應用。