Los valores de DateTime remotos de un objeto DataSet se convierten a la hora local equivalente de un equipo remoto que está en una zona horaria diferente

Seleccione idioma Seleccione idioma
Id. de artículo: 842545 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Resumen

cuando se pasa un objeto de la clase DataSet a un servicio Web remoto o a un servicio Web que está en una zona horaria que es diferente de la zona horaria de la aplicación de llamada, las columnas DateTime de una tabla contenida se convierten a la hora local equivalente. Las columnas DateTime se convierten porque el código de System.Data.DataSet se ajusta a la hora local equivalente de acuerdo con la zona horaria del equipo remoto. Por ejemplo, si un valor de 5: 00 se pasa desde el equipo cliente de hora del Pacífico a un servicio Web en la hora, el valor en el objeto DataSet se cambia a las 8: 00 en el método receptor del servicio Web. En este artículo se describe cómo evitar este problema por pasar la información de zona horaria de la aplicación cliente al servicio Web y ajustar las columnas DateTime en el equipo remoto. El System.Data es el espacio de nombres que contiene la clase de DataSet.

Síntomas

Los valores de las columnas DateTime cambian cuando se pasa un objeto System.Data.DataSet a un servicio Web o a un servicio Web remoto. Este problema se produce cuando el servicio Web o servicio Web remoto está en una zona horaria diferente que la aplicación cliente. Los valores de las columnas DateTime se convierten a la hora local equivalente de acuerdo con la zona horaria del equipo remoto.

Causa

La zona horaria de la aplicación cliente se almacena durante la serialización de objeto DataSet . Se deserializa el objeto DataSet al receptor final y el código de System.Data.DataSet ajusta las columnas DateTime a la hora local equivalente del equipo remoto que está en una zona horaria diferente.

Solución

Para evitar este problema, debe pasar información sobre la zona horaria cuando se crea el objeto DataSet en la aplicación cliente y, a continuación, debe ajustar el objeto DataSet después de recibir en el proceso llamado en el equipo remoto. Para ello, siga estos pasos:
  1. En el proyecto de servicio Web en el equipo remoto, escriba código que ajusta los valores de DateTime de acuerdo con la zona horaria de la aplicación cliente. Para ello, siga estos pasos:
    1. Agregue el código siguiente en el Service1 clase tal como se especifica en la sección "Crear un servicio 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;
      }
      
      el método AdjustDSTimeZone ajusta los valores DateTime para reflejar la hora original de la aplicación cliente. Aquí ExtendedProperties propiedad de la clase DataSet se utiliza para almacenar el desplazamiento de hora universal coordinada (UTC) con el objeto DataSet . Con la propiedad ExtendedProperties , puede almacenar información personalizada con el objeto DataSet . Si desea que el objeto DataSet remoto, debe almacenar el desplazamiento de UTC como una cadena en ExtendedProperties colección.
    2. Agregue el código siguiente debajo de la AdjustDSTimeZone método:
      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. En el menú archivo , haga clic en Guardar todo para guardar la aplicación.
    4. En el menú Generar , haga clic en Generar solución para generar la aplicación.
    El método AdjustDateTimeValues realiza el ajuste para el objeto DateTime . Se obtiene la hora original de la columna DateTime de una fila determinada y, a continuación, se modifica según a la hora local de la aplicación cliente.
  2. En la aplicación cliente, escribir código que comprueba que el servicio Web ha ajustado la información de zona horaria. Para ello, siga estos pasos:
    1. Agregue el código siguiente en la principal función después del código que se especifica en la sección "Crear una aplicación de cliente":
      str=myDatasetService.AdjustDSTimeZone(myDataset );
      Console.WriteLine (str);
      Console.ReadLine ();
    2. En el Explorador de soluciones, expanda todas las carpetas.
    3. Haga clic con el botón secundario del mouse en WebReference1 y, a continuación, haga clic en Actualizar referencia Web .
    4. En el menú archivo , haga clic en Guardar todo para guardar la aplicación.
    5. En el menú Generar , haga clic en Generar solución para generar la aplicación.
    6. En el menú Depurar , haga clic en iniciar para ejecutar la aplicación.
La aplicación de cliente se conecta a la tabla MyTable que contiene una columna DateTime. Crea un objeto del servicio Web y pasa un objeto de la clase DataSet al método AdjustDSTimeZone del Web service. El método AdjustDSTimeZone en el servicio Web actualiza el campo DateTime columna de la MyTable tabla según la zona horaria de la aplicación de cliente y, a continuación, devuelve el valor de DateTime de la primera fila de la tabla MyTable. El valor de DateTime que es recibido por la aplicación de cliente es igual al valor que se pasa por la aplicación de cliente en el Web service.

Estado

Este comportamiento es por diseño.

Más información

Pasos para reproducir el problema

Crear una tabla de base de datos

Para crear una tabla de base de datos en una instancia de Microsoft SQL Server, siga estos pasos:
  1. Inicie el Analizador de consultas de SQL.
  2. En el menú archivo , haga clic en nuevo .
  3. Haga clic en Ventana de consulta en blanco y, a continuación, haga clic en Aceptar .
  4. Pegue el código siguiente en la ventana de consulta. Este código crea la tabla MyTable.
    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
    
    
  5. En el menú consulta , haga clic en Ejecutar para ejecutar la consulta. El MyTable tabla se crea y se actualiza la tabla con dos valores.

Crear un servicio Web

Crear un proyecto de servicio Web en un equipo remoto que recibe los valores de DateTime desde una aplicación cliente. Para ello, siga estos pasos:
  1. Inicie Microsoft Visual Studio NET..
  2. En el menú archivo , seleccione nuevo y, a continuación, haga clic en proyecto .
  3. En Tipos de proyecto , haga clic en Proyectos de Visual C# y, a continuación, haga clic en Servicio Web ASP.NET bajo plantillas .
  4. En el cuadro nombre , escriba MyWebService y, a continuación, haga clic en Aceptar . De forma predeterminada, se crea el archivo Service1.asmx.
  5. En el Explorador de soluciones, haga clic con el botón secundario en el archivo Service1.asmx y, a continuación, haga clic en Ver código .
  6. Agregue el código siguiente al principio del archivo:
    using System.Data.SqlClient;
    using System.Timers;
  7. Busque el código siguiente en Service1 de la clase:
    public class Service1 : System.Web.Services.WebService
    {
  8. Agregue el código siguiente después del código que encontró en el paso 7:
    [WebMethod]
    public String DataSetReturn( DataSet clientDataSet )
    {
      string str;				
      str=clientDataSet.Tables["MyTable"].Rows[0][1].ToString() ;
      return str;	
    }
    el método DataSetReturn recibe un objeto del DataSet que se pasa por la aplicación cliente. Este método devuelve el valor de DateTime de la primera fila de la tabla MyTable a la aplicación cliente.
  9. En el menú archivo , haga clic en Guardar todo para guardar la aplicación.
  10. En el menú Generar , haga clic en Generar soluciones para generar la aplicación.

Crear una aplicación cliente

Para crear una aplicación de cliente que pasa un objeto DataSet al servicio Web remoto, siga estos pasos:
  1. Inicie Microsoft Visual Studio NET..
  2. En el menú archivo , seleccione nuevo y, a continuación, haga clic en proyecto .
  3. En Tipos de proyecto , haga clic en Proyectos de Visual C# y, a continuación, haga clic en Aplicación de consola , bajo plantillas .
  4. En el cuadro nombre , escriba MyDataSet y, a continuación, haga clic en Aceptar . De forma predeterminada, se crea el archivo Class1.cs.
  5. Agregue el código siguiente al principio del archivo:
    using System.Data;
    using System.Data.SqlClient;
    using System.Timers;
    using System.Diagnostics;
  6. Agregue el código siguiente en el principal función:
    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 ();
    
    Nota para tener acceso a la MyTable tabla, se deben modificar la información del servidor y la información de base de datos junto con el nombre de usuario y la contraseña para establecer la conexión con Microsoft SQL Server.
  7. En el Explorador de soluciones, haga clic con el botón secundario en referencias y, a continuación, haga clic en Agregar referencia Web .
  8. En el cuadro dirección URL , escriba http:// RemoteServer /MyWebService/Service1.asmx y, a continuación, haga clic en Ir . De forma predeterminada, en un Web se crea la referencia que se denomina WebReference1 de Visual Studio .NET 2002.

    Nota RemoteServer es un marcador de posición para el nombre del servidor remoto donde se crea el servicio Web.
  9. En Microsoft Visual Studio .NET 2003, escriba WebReference1 en el nombre de referencia Web del cuadro. Aquí WebReference1 se utiliza para que coincida con la sintaxis de código.
  10. Haga clic en agrega referencia .
  11. En el menú archivo , haga clic en Guardar todo para guardar la aplicación.
  12. En el menú Generar , haga clic en Generar soluciones para generar la aplicación.
  13. En el menú Depurar , haga clic en iniciar para ejecutar la aplicación.
La aplicación cliente modifica la columna DateTime de la primera fila. El código establece el valor de DateTime a la fecha actual y la hora de la aplicación cliente. Pasa un objeto DataSet al servicio Web. El servicio Web recibe el objeto DataSet , recupera el valor de la columna DateTime de la primera fila y, a continuación, devuelve el valor nuevo a la aplicación cliente. Se cambia el valor DateTime devuelto por el servicio Web según a la información de zona horaria del servidor remoto como especificada en la sección "Síntomas" sección.

Interacción remota de .NET framework

Si va a implementar los servicios de interacción remota de .NET Framework en la aplicación y no se llama a un método de servicio Web de .NET Framework, puede utilizar el código de la clase DataSetSurrogate .Para obtener información adicional acerca de la clase DataSetSurrogate, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
829740Mejorar el rendimiento DataSet de serialización y la interacción remota
La clase DataSetSurrogate impide que los ajustes de zona horaria local en las columnas DateTime. Esta clase también proporciona un mejor rendimiento durante la interacción remota de .NET Framework. La clase DataSetSurrogate reemplaza la serialización predeterminada de la clase DataSet y serializa la clase DataSetSurrogate y sus miembros contenidos en formato binario.

Referencias

Para obtener más información, visite los siguientes sitios Web de Microsoft Developer Network (MSDN):
System.Data.SqlClient espacio de nombres
http://msdn2.microsoft.com/en-us/library/system.data.sqlclient(vs.71).aspx
DataSet.ExtendedProperties propiedad
http://msdn2.microsoft.com/en-us/library/system.data.dataset.extendedproperties(vs.71).aspx

Propiedades

Id. de artículo: 842545 - Última revisión: viernes, 18 de mayo de 2007 - Versión: 1.5
La información de este artículo se refiere a:
  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
Palabras clave: 
kbmt kbtshoot kbwebservices kbremoting kbclient kbsystemdata kbsqlclient kbservice kbprb KB842545 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 842545

Enviar comentarios

 

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