遠端 DataSet 物件中的日期時間值轉換成處於不同時區的遠端電腦的對等的本機時間

重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。

按一下這裡查看此文章的英文版本:842545
本文已封存。本文係以「現狀」提供且不會再更新。
結論
當您傳遞資料集類別的物件到遠端的 Web 服務或 Web 服務,不同於呼叫的應用程式的時區的時區,所包含的資料表中的日期時間資料行轉換為相等的本地時間。因為 System.Data.DataSet 程式碼會調整,以根據到遠端電腦的 「 時間 」 區域對等的本機時間轉換日期時間資料行。比方說如果 5: 00 的值會從傳送用戶端電腦在太平洋時間至 Web 服務在美加東部時間,DataSet 物件中的值則會變更成 8: 00 的 Web 服務接收的方法。本文將告訴您,如何解決這個問題,藉由將時區資訊傳遞到 Web 服務用戶端應用程式,以及調整日期時間資料行,在遠端電腦。[System.Data 是命名空間包含的資料集 class.
徵狀
當您將 System.Data.DataSet 物件傳遞至 Web 服務或遠端的 Web 服務時,就會改變日期時間資料行的值。當您的 Web 服務或遠端 Web 服務是在不同的時區,比用戶端應用程式時,就會發生這個問題。日期時間資料行中的值會轉換成相等的本地時間,根據到遠端電腦的 「 時間 」 區域。
發生的原因
用戶端應用程式的時區儲存在 DataSet 物件序列化期間。DataSet 物件還原序列化接收結尾並 System.Data.DataSet 程式碼會調整為相等的當地時間處於不同時區的遠端電腦的日期時間資料行。
其他可行方案
如果要解決這個問題,您必須在用戶端應用程式中建立 資料集 物件,並接收遠端電腦上被呼叫的程序中後您必須再調整 DataSet 物件時傳遞時區的相關資訊。要這麼做,請您執行下列步驟:
  1. 在 [Web 服務專案遠端電腦上,寫入調整 日期時間 值,根據 「 時間 」 區域,用戶端應用程式的程式碼。要這麼做,請您執行下列步驟:
    1. 加入下列程式碼中 Service1 < 建立 Web 服務 > 一節中所指定類別:
      [WebMethod]public string AdjustDSTimeZone( DataSet dataSet ) { // Obtains the time difference on the sender computer that //remoted this dataset to the Web service. string str;	 string sourceTicksString = dataSet.ExtendedProperties["UTCDifference"].ToString(); long sourceTicks = long.Parse( sourceTicksString ); // Obtain the UTC offset for the remote computer. DateTime baseUTC = DateTime.Now; long UtcTickslocal = TimeZone.CurrentTimeZone.GetUtcOffset( baseUTC ).Ticks; // Obtain the time difference between the sender computer and the remote computer. long ticksDifference = sourceTicks - UtcTickslocal; TimeSpan timespan = new TimeSpan( ticksDifference );  // The following code iterates through each table, and find all the columns that are  // DateTime columns. After identifying the columns that have to be adjusted, // it traverses the data in the table and adjusts the DateTime columns back to their  // original values. You must leave the RowState of the DataRow in the same state  //after making the adjustments. foreach( DataTable table in dataSet.Tables )  {  DataColumnCollection columns = table.Columns;  int[] ColumnNumbers = new int[columns.Count];  int   ColumnNumbersIndex = 0;  for( int i = 0; i < columns.Count; i++ )   {   DataColumn col = columns[i];   if ( col.DataType == typeof( DateTime ) )    {	 	ColumnNumbers[ColumnNumbersIndex] = i;	ColumnNumbersIndex++;   } } foreach( DataRow row in table.Rows )  {  switch ( row.RowState )   {   case DataRowState.Unchanged:    AdjustDateTimeValues( row, ColumnNumbers,    ColumnNumbersIndex, timespan );    row.AcceptChanges();	// This is to make sure that the    // row appears to be unchanged again.    Debug.Assert( row.RowState == DataRowState.Unchanged );    break;   case DataRowState.Added:    AdjustDateTimeValues( row, ColumnNumbers, ColumnNumbersIndex, timespan );    // The row is still in a DataRowState.Added state.    Debug.Assert( row.RowState == DataRowState.Added );     break;   case DataRowState.Modified:     AdjustDateTimeValues( row, ColumnNumbers, ColumnNumbersIndex, timespan );    // The row is a still DataRowState.Modified.    Debug.Assert( row.RowState == DataRowState.Modified );    break;   case DataRowState.Deleted:    //   This is to make sure that you obtain the right results if     //the .RejectChanges()method is called.    row.RejectChanges();	// This is to "undo" the delete.    AdjustDateTimeValues( row, ColumnNumbers, ColumnNumbersIndex, timespan );	    // To adjust the datatime values.    // The row is now in DataRowState.Modified state.    Debug.Assert( row.RowState == DataRowState.Modified );    row.AcceptChanges();	// This is to mark the changes as permanent.    Debug.Assert( row.RowState == DataRowState.Unchanged );    row.Delete();			    // Delete the row. Now, it has the same state as it started.    Debug.Assert( row.RowState == DataRowState.Deleted );    break;    default:    throw new ApplicationException    ( "You must add a case statement that handles the new version of the dataset." );   }  } }  str=dataSet.Tables["MyTable"].Rows[0][1].ToString() ;  return str;}
      AdjustDSTimeZone 方法會調整 日期時間 值,以反映用戶端應用程式的原始時間。這裡 ExtendedProperties資料集 類別的屬性用來儲存定位國際時間 (UTC) 位移與 資料集 物件。與 ExtendedProperties] 屬性中,您可以將儲存與 資料集 物件的自訂資訊。視 資料集 物件成為遠端 UTC 位移必須儲存為 ExtendedProperties 中的字串集合。
    2. 加入下列程式碼下方 AdjustDSTimeZone 方法:
      void AdjustDateTimeValues( DataRow row, int[] ColumnNumbers, int columnCount, TimeSpan timespan) {  for ( int i = 0; i < columnCount; i++ )   {	int columnIndex = ColumnNumbers[i];	DateTime original = (DateTime)row[columnIndex];	DateTime modifiedDateTime = original.Add(timespan);	row[columnIndex] = modifiedDateTime;  }}
    3. 在 [檔案] 功能表上按一下 [另 儲存全部 儲存應用程式新檔]。
    4. 建置] 功能表上按一下 [建置方案] 建置應用程式]。
    AdjustDateTimeValues 方法進行到 日期時間 物件調整。它會從的特定資料列的 [日期時間] 資料行中取得原始的時間,然後再修改根據為用戶端應用程式的本機時間。
  2. 在用戶端應用程式中撰寫程式碼,會驗證 Web 服務已調整時區資訊。要這麼做,請您執行下列步驟:
    1. Main 中加入下列程式碼之後的 < 建立用戶端應用程式 > 一節中所指定的程式碼的函式:
      str=myDatasetService.AdjustDSTimeZone(myDataset );Console.WriteLine (str);Console.ReadLine ();
    2. 在 [方案總管] 中展開 [所有資料夾]。
    3. WebReference1,] 上按一下滑鼠右鍵,然後按一下 [更新 Web 參考
    4. 在 [檔案] 功能表上按一下 [另 儲存全部 儲存應用程式新檔]。
    5. 建置] 功能表上按一下 [建置方案] 建置應用程式]。
    6. 在 [偵錯] 功能表上按一下 [開始] 執行應用程式]。
用戶端應用程式則會連結到包含日期時間資料行的 MyTable 資料表。它會建立 Web 服務的物件,並將 資料集 類別的物件傳遞至 AdjustDSTimeZone 方法的 Web 服務。Web 服務中的 [AdjustDSTimeZone] 方法會更新日期時間欄 [MyTable 的資料表根據用戶端應用程式,然後傳回的時區 MyTable 資料表的第一列的日期時間值。用戶端應用程式所收到的 日期時間 值會傳遞至 Web 用戶端應用程式時的值相同服務。
狀況說明
這種行為是經過設計規劃的。
其他相關資訊

如果要重現問題的步驟

建立資料庫表格

若要在 Microsoft SQL 的執行個體中建立一個資料庫資料表伺服器,請依照下列步驟執行:
  1. 啟動 SQL 查詢分析。
  2. 按一下 [檔案] 功能表 新增]
  3. 按一下 [空白查詢視窗,然後按一下 [確定]
  4. 下列程式碼貼在 [查詢] 視窗中。這個程式碼會建立
    CREATE  TABLE MyTable (            [ID] [int] NOT NULL ,            [DateTimeCol] [datetime] NOT NULL ) ON [PRIMARY]GoInsert into MyTable Values (1, '2004-05-19 15:00:00.000')GoInsert into MyTable Values (2, '2004-05-19 13:00:00.000')Go
    MyTable 的資料表。
  5. 按一下 [查詢] 功能表,執行查詢的 執行。[MyTable 建立資料表,資料表會更新以兩個值。

建立 Web 服務

從用戶端應用程式接收 日期時間 值的遠端電腦上建立 Web 服務專案。要這麼做,請您執行下列步驟:
  1. 啟動 Microsoft Visual Studio.NET。
  2. 在 [檔案] 功能表上指向 [新增],然後按一下 [專案]。
  3. 在 [專案類型 下, 按一下 [Visual C# 專案,] 然後按一下 [範本] 下方的 [ASP.NET Web 服務]。
  4. 在 [名稱] 方塊中輸入 MyWebService,],然後再按一下 [確定]]。預設情況下,會建立 Service1.asmx 檔案。
  5. 在 [方案總管] 中 Service1.asmx] 檔案上按一下滑鼠右鍵,然後按一下 [檢視程式碼
  6. 檔案的開頭加入下列程式碼:
    using System.Data.SqlClient;using System.Timers;
  7. 找出下列的程式碼中 Service1 類別:
    public class Service1 : System.Web.Services.WebService{
  8. 將下列程式碼加入您在步驟 7 中找到程式碼之後:
    [WebMethod]public String DataSetReturn( DataSet clientDataSet ){  string str;				  str=clientDataSet.Tables["MyTable"].Rows[0][1].ToString() ;  return str;	}
    DataSetReturn 方法會接收由用戶端應用程式傳遞 資料集 的物件。這個方法會傳回給用戶端應用程式的第一列 MyTable 資料表的 日期時間 值。
  9. 在 [檔案] 功能表上按一下 [另 儲存全部 儲存應用程式新檔]。
  10. 在 [建置] 功能表上按一下 建置方案 來建置應用程式。

建立用戶端應用程式

若要建立將 DataSet 物件傳遞至遠端 Web 服務的用戶端應用程式,請依照下列步驟執行:
  1. 啟動 Microsoft Visual Studio.NET。
  2. 在 [檔案] 功能表上指向 [新增],然後按一下 [專案]。
  3. 在 [專案類型 下, 按一下 [Visual C# 專案,] 然後按一下 [範本] 下方的 [主控台應用程式]。
  4. 在 [名稱] 方塊中輸入 MyDataSet,],然後再按一下 [確定]]。預設情況下,會建立 Class1.cs 檔案。
  5. 檔案的開頭加入下列程式碼:
    using System.Data;using System.Data.SqlClient;using System.Timers;using System.Diagnostics;
  6. Main 中加入下列程式碼函式:
    string auth="Server=YourServer;Database=YourDatabase;User ID=YourUserID;password=YourPassword";WebReference1.Service1 myDatasetService = new WebReference1.Service1();DataSet myDataset = new DataSet();SqlDataAdapter da = new SqlDataAdapter("Select * From MyTable",auth);da.Fill(myDataset, "MyTable");//Modify first row to have the current time.myDataset.Tables["MyTable"].Rows[0][1] = DateTime.Now;string str=myDataset.Tables["MyTable"].Rows[0][1].ToString() ;System.Console.WriteLine(str);//Store the ticks from UTC in the ExtendedProperties collection of the DataSetDateTime clientDateTime = DateTime.Now;myDataset.ExtendedProperties["UTCDifference"] = TimeZone.CurrentTimeZone.GetUtcOffset( clientDateTime ).Ticks.ToString();    str= myDatasetService.DataSetReturn(myDataset );Console.WriteLine (str);Console.ReadLine ();
    附註 若要存取 [MyTable 表格,您必須修改伺服器資訊和資料庫資訊一起以使用者名稱和密碼來建立和 Microsoft SQL Server 連線。
  7. 在 [方案總管] 中以滑鼠右鍵按一下 [參考],然後按一下 [加入 Web 參考]。
  8. 在 [URL] 方塊輸入 http:// RemoteServer /MyWebService/Service1.asmx,然後按一下 []。在 Web,建立名為 WebReference1 的參照 Visual Studio.NET 2002年中預設。

    附註RemoteServer 是預留位置建立 Web 服務的遠端伺服器的名稱。
  9. 在 Visual Studio.NET 2003 Microsoft,輸入 WebReference1Web 參考名稱] 方塊中。這裡 WebReference1 用來符合程式碼語法。
  10. 按一下 [加入參考]。
  11. 在 [檔案] 功能表上按一下 [另 儲存全部 儲存應用程式新檔]。
  12. 在 [建置] 功能表上按一下 建置方案 來建置應用程式。
  13. 在 [偵錯] 功能表上按一下 [開始] 執行應用程式]。
用戶端應用程式修改第一個資料列的日期時間資料的行。程式碼會將 日期時間 值設定為目前的日期和時間的用戶端應用程式。將 DataSet 物件傳遞至 Web 服務。Web 服務接收 資料集 物件,從第一列擷取日期時間資料行的值與值傳回給用戶端應用程式。變更由 Web 服務所傳回的 日期時間 值根據為遠端伺服器的時區資訊作為中所指定之 < 徵狀 > 一節。

.NET Framework 遠端處理

如果您正在實作.NET Framework 遠端服務應用程式中,而且您不會呼叫.NET Framework Web 服務方法您可以使用 DataSetSurrogate 類別的程式碼。取得更多資訊有關 DataSetSurrogate 類別按一下 [下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項]:
829740增進資料集序列化和遠端效能
DataSetSurrogate 類別可防止本地時間區域調整日期時間資料行上。這個類別也會提供較佳的效能,在.NET Framework 遠端處理期間。DataSetSurrogate 類別覆寫預設序列化的 資料集 類別,並將序列化 DataSetSurrogate 類別和它所包含的成員的二進位形式。
参考
如需詳細資訊請造訪下列 Microsoft 開發人員網路 (MSDN) 網站:
遠端處理資料集物件變更的日期時間值,當遠端 DateTime 變更值時在不同時區的 Web 服務的遠端

警告:本文為自動翻譯

內容

文章識別碼:842545 - 最後檢閱時間:12/08/2015 07:23:31 - 修訂: 1.5

Microsoft .NET Framework 1.1, Microsoft .NET Framework 1.0

  • kbnosurvey kbarchive kbmt kbtshoot kbwebservices kbremoting kbclient kbsystemdata kbsqlclient kbservice kbprb KB842545 KbMtzh
意見反應