DataSet 对象中的远程访问 DateTime 值转换为等效的本地时间,处于不同时区的远程计算机的

文章翻译 文章翻译
文章编号: 842545 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

概要

传递时的 DataSet 类的对象到远程 Web 服务或 Web 服务的调用的应用程序的时区不同的时区中,一个包含表中的 DateTime 列将转换为等效的本地时间。DateTime 列被转换,因为 System.Data.DataSet 代码调整为等效的本地时间,根据到远程计算机的时区。例如对于如果值为 5: 00 从太平洋时间中的客户端计算机向 Web 服务传递在东部时间,DataSet 对象中值更改为 8: 00 的 Web 服务接收的方法中。本文介绍如何通过从 Web 服务客户端应用程序传递时区信息,并通过调整 DateTime 列,在远程计算机上的解决此问题。在 System.Data 是命名空间包含 DataSet class.

症状

日期时间列的值更改时将 System.Data.DataSet 对象传递到 Web 服务或远程的 Web 服务。当您的 Web 服务或远程 Web 服务处于不同时区比客户端应用程序时,将发生此问题。日期时间列中的,值被转换为等效的本地时间,根据到远程计算机的时区。

原因

数据集 对象序列化过程中存储的客户端应用程序的时区。在在接收端的 DataSet 对象进行反序列化并 System.Data.DataSet 代码调整为等效的本地时间,处于不同时区的远程计算机的日期时间列。

替代方法

要变通解决此问题,您必须通过的时区信息时 DataSet 对象在客户端应用程序中创建的然后在远程计算机上被调用过程中收到之后您必须调整 DataSet 对象。若要这样做,请按照下列步骤操作:
  1. 在远程计算机上 Web 服务项目在编写代码的调整 DateTime 值根据客户端应用程序的时区。若要这样做,请按照下列步骤操作:
    1. 在 $ 服务 1 中添加下面的代码在"创建 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 方法调整 DateTime 值,以反映原始客户端应用程序的时间。此处 ExtendedPropertiesDataSet 类的属性用来存储协调世界时 (UTC) 偏移量与 DataSet 对象。与 ExtendedProperties 属性中,您可以将存储自定义信息与 DataSet 对象。您是否要进行远程访问 DataSet 对象必须将 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 方法使得将调整 DateTime 对象。它从日期时间列的特定行获取原始时间,然后修改根据向客户端应用程序的本地时间。
  2. 在客户端应用程序编写代码以验证该 Web 服务已经调整时区信息。若要这样做,请按照下列步骤操作:
    1. 添加以下代码在 Main 函数在"创建客户端应用程序"一节中指定的代码之后:
      str=myDatasetService.AdjustDSTimeZone(myDataset );
      Console.WriteLine (str);
      Console.ReadLine ();
    2. 在解决方案资源管理器中,展开所有文件夹。
    3. 用鼠标右键单击 WebReference1,然后单击 更新 Web 引用
    4. 文件 菜单上单击 全部保存 以保存应用程序。
    5. 生成 菜单上单击 生成解决方案,以生成应用程序。
    6. 调试 菜单上单击 $ 开始 以运行该应用程序。
客户端应用程序连接到 MyTable 表包含 DateTime 列。创建 Web 服务的对象,并将 数据集 类的对象传递给 AdjustDSTimeZone 方法的 Web 服务。在 Web 服务中的 AdjustDSTimeZone 方法更新该 DateTime 列的该 MyTable 表根据时区的客户端应用程序,然后返回 MyTable 表中的第一行的日期时间值。客户端应用程序接收到的 日期时间 值是相等,则传递到 Web 客户端应用程序的服务。

状态

此行为是设计使然。

更多信息

重现此问题的步骤

创建数据库表

若要创建的数据库表 Microsoft SQL Server 的一个实例中,请按照下列步骤操作:
  1. 启动 SQL 查询分析器。
  2. 文件 菜单上单击 新建
  3. 单击 空白查询窗口,然后单击 确定
  4. 在查询窗口中,请将以下代码粘贴。此代码创建
    CREATE  TABLE MyTable (
    
                [ID] [int] NOT NULL ,
    
                [DateTimeCol] [datetime] NOT NULL 
    
    ) ON [PRIMARY]
    
    Go
    Insert into MyTable Values (1, '2004-05-19 15:00:00.000')
    Go
    
    Insert into MyTable Values (2, '2004-05-19 13:00:00.000')
    Go
    
    
    MyTable 表。
  5. 查询 菜单上单击以运行查询的 执行。在 MyTable 表创建,并将更新表具有两个值。

创建的 Web 服务

从客户端应用程序接收 DateTime 值的远程计算机上创建的 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. 服务 1 中找到下面的代码类:
    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. 生成 菜单上单击 生成解决方案 生成应用程序。

创建客户端应用程序

若要进行一个客户端应用程序传递到远程 Web 服务的 DataSet 对象,请按照下列步骤操作:
  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 DataSet
    DateTime 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,然后单击 搜索。Visual Studio.net 2002,会创建名为 WebReference1 引用网站中的默认。

    注意RemoteServer 是创建 Web 服务的位置在远程服务器的名称的占位符。
  9. 在 Microsoft Visual Studio.net 2003年键入 WebReference1Web 引用名 框中。在此处 WebReference1 用于匹配代码语法。
  10. 单击 添加引用
  11. 文件 菜单上单击 全部保存 以保存应用程序。
  12. 生成 菜单上单击 生成解决方案 生成应用程序。
  13. 调试 菜单上单击 $ 开始 以运行该应用程序。
客户端应用程序修改第一行 DateTime 的列。该代码将 DateTime 值设置为当前日期和时间的客户端应用程序。它将传递到 Web 服务的 DataSet 对象。Web 服务接收 DataSet 对象,从第一个行中检索的 DateTime 列的值,然后返回到客户端应用程序,返回值。由 Web 服务返回的 日期时间 值会根据到远程服务器的时区信息,以指定在"症状"一节。

.NET 框架远程处理

如果要在您的应用程序中实现.net Framework 远程处理服务,并且不调用一个.net 框架 Web 服务方法可以使用 DataSetSurrogate 类代码。有关 DataSetSurrogate 类的其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
829740提高 DataSet 序列化和远程处理性能
DataSetSurrogate 类可防止本地时间区域调整 DateTime 列上。此类还提供了更好的性能,在.net Framework 远程处理过程中。DataSetSurrogate 类重写默认序列化 数据集 类的并将 DataSetSurrogate 类和它包含的成员,以二进制形式序列化。

参考

有关更多的信息,请访问下面的 Microsoft 开发人员网络 (MSDN) 的网站:
System.Data.SqlClient 命名空间
http://msdn2.microsoft.com/en-us/library/system.data.sqlclient(vs.71).aspx
DataSet.ExtendedProperties 属性
http://msdn2.microsoft.com/en-us/library/system.data.dataset.extendedproperties(vs.71).aspx

属性

文章编号: 842545 - 最后修改: 2007年5月18日 - 修订: 1.5
这篇文章中的信息适用于:
  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
关键字:?
kbmt kbtshoot kbwebservices kbremoting kbclient kbsystemdata kbsqlclient kbservice kbprb KB842545 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 842545
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com