2016-02-26 3 views
1

Nous avons un système de formulaires Windows (DNF2!)/Remoting (!)/SQL Server (2008R2!) Sur le Web qui a été heureusement passé tapé assez grand et varié DataSets dans les deux sens à travers le web à partir de différents fuseaux horaires."SqlDateTime overflow" erreur avec DataSets sur remoting

Nous avons récemment amélioré le système et les choses semblaient bonnes jusqu'à ce que les utilisateurs commencent à recevoir des erreurs sporadiques de "débordement SqlDateTime" (trace de pile ci-dessous). Sporadique i.t. certaines tables causaient des problèmes à l'occasion, d'autres pas du tout.

Nous avons fini par comprendre que cela ne se produisait que lorsque les fuseaux horaires du client et du serveur Web différaient - derrière ou devant.

De même, il se produit uniquement si un champ DateTime est vide! A partir de la trace de la pile, il apparaît qu'il s'agit d'un problème de sérialisation. Cela a été confirmé lors de l'enquête qui montre qu'il frappe le BL sur le serveur web (My.Application.Log.WriteEntry montre le champ date avec date ou NULL) mais ne frappe pas la base de données (SQL Profiler ne montre rien).

Nous avons remarqué au cours de débogage que nous obtenions un avertissement MDA:

A UTC DateTime est converti en texte dans un format qui est seulement correct pour l'heure locale. Cela peut se produire lors de l'appel de DateTime.ToString en utilisant le spécificateur de format 'z', qui inclura un décalage de fuseau horaire local dans la sortie. Dans ce cas, utilisez le spécificateur de format 'Z', qui désigne une heure UTC, ou utilisez la chaîne de format 'o', qui est la méthode recommandée pour conserver un DateTime dans le texte. Cela peut également se produire lors de la transmission d'un DateTime à sérialiser par XmlConvert ou DataSet. Si vous utilisez XmlConvert.ToString, passez XmlDateTimeSerializationMode.RoundtripKind pour sérialiser correctement. Si vous utilisez DataSet, définissez le DateTimeMode de l'objet DataColumn sur DataSetDateTime.Utc.

Nous docilement suivi les conseils de BillG (c.-à-changer le DateTimeMode à UTC), mais cela ne change rien du tout :(

Nous avons trouvé la modification de tous les champs DateTime au texte a également résolu le problème bien que cela nous laisse grand ouverts à d'autres questions plutôt sérieuses!

Donc, même si nous avons quelques solutions de rechange, elles ne sont pas des solutions viables

Une note de côté - nous essayions également de faire une compression sur certaines des données DataSet (conversion de l'ensemble DataSet en un flux d'octets et en utilisant le System.IO.Compression), mais cette erreur n'était pas toujours trouvée dans les DataSets compressés - et d'ailleurs on a complètement enlevé la compression tout en s'accrochant aux pailles!

System.Data.SqlTypes.SqlTypeException: SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM. 

Server stack trace: 
    at System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount) 
    at System.Data.Common.DbDataAdapter.UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount) 
    at System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows, DataTableMapping tableMapping) 
    at System.Data.Common.DbDataAdapter.UpdateFromDataTable(DataTable dataTable, DataTableMapping tableMapping) 
    at System.Data.Common.DbDataAdapter.Update(DataTable dataTable) 
    at K2.ADAMData.MaterialDataSetTableAdapters.MaterialTableAdapter.Update(MaterialDataTable dataTable) 
    at K2.ADAMServerClasses.Material.SaveMaterials(Byte[] EncConStr, MaterialDataTable ChangesTable) 
    at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs) 
    at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext) 

Exception rethrown at [0]: 
    at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) 
    at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) 
    at K2.ADAMServerClasses.Material.SaveMaterials(Byte[] EncConStr, MaterialDataTable ChangesTable) 
    at K2.ADAM.MaterialEditForm.SaveData() in C:\Data\Clients\K2\Software\ADAM\Development\2.1 HHI\UI\Forms\MaterialEditForm.vb:line 279 
    at K2.ADAM.MaterialEditForm.SaveButton_Click(Object sender, EventArgs e) in C:\Data\Clients\K2\Software\ADAM\Development\2.1 HHI\UI\Forms\MaterialEditForm.vb:line 551 

Répondre

1

Ainsi, tout en préparant cette question, j'ai eu une épiphanie ...

Dès le début tout en travaillant sur l'amélioration des performances (la sérialisation des DataSets était d'environ 8 fois la taille des données réelles!) Nous avons changé le DataSet.RemotingFormat=Binary.

Eh bien, soufflez-moi si cela ne perd pas l'intrigue lorsque présenté avec un fuseau horaire différent!

Je ne peux que supposer que la sérialisation binaire fait quelque chose de bizarre avec NULLs? Peut-être qu'il utilise "1-Janvier-0001" avec un attribut "isNull = true" ou quelque chose?

Anyhoo, changez le DataSet.RemotingFormat=XML et les utilisateurs sont encore heureux - et même la compression de flux fonctionne dandy. Remarque pour auto - NE PAS utiliser le format d'accès binaire à distance avec des dates SQL.

+0

Merci d'être revenu et de poster vos résultats –