locked
Invalid cast from 'System.DateTime' to 'System.Byte[]' SoapException during 'GetChanges' RRS feed

  • Question

  •  

    Hi,  I have added batching/anchor to my Sync application as per examples on the net from msdn and SyncGuru.  The code compiles but generates a exception while invoking 'GetChanges' :

     

    SoapException occured: Server was unable to process request. ---> Failed to convert parameter value from a DateTime to a Byte[]. ---> Invalid cast from 'System.DateTime' to 'System.Byte[]'.

     

    From what i can tell this happens just before I call the Stored Procedure to set the anchor timestamps.  As the code to call the stored procedure is hidden I am unsure how to debug / solve this problem.  Code used to activte the batching/anchor :

     

    SqlCommand selectNewAnchorCommand = new SqlCommand();

    selectNewAnchorCommand.Connection = (SqlConnection)this.Connection;

    selectNewAnchorCommand.CommandText = "usp_GetNewBatchAnchor";

    selectNewAnchorCommand.CommandType = CommandType.StoredProcedure;

    selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncLastReceivedAnchor, SqlDbType.Timestamp);

    selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncBatchSize, SqlDbType.Int);

    selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncMaxReceivedAnchor, SqlDbType.Timestamp).Direction = ParameterDirection.InputOutput;

    selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncNewReceivedAnchor, SqlDbType.Timestamp).Direction = ParameterDirection.Output;

    selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncBatchCount, SqlDbType.Int).Direction = ParameterDirection.InputOutput;

    //

    this.SelectNewAnchorCommand = selectNewAnchorCommand;

    this.BatchSize = 100;

     

     

    Any assistance is GREATLY appreciated.

    • Moved by Hengzhe Li Friday, April 22, 2011 2:10 AM (From:SyncFx - Microsoft Sync Framework Database Providers [ReadOnly])
    Wednesday, September 10, 2008 3:18 AM

All replies

  • Can you post complete exception stack trace?

     

    Wednesday, September 10, 2008 8:17 PM
    Moderator
  •    at System.Data.SqlClient.SqlParameter.CoerceValue(Object value, MetaType destinationType)
       at System.Data.SqlClient.SqlParameter.GetCoercedValue()
       at System.Data.SqlClient.SqlParameter.Validate(Int32 index, Boolean isCommandProc)
       at System.Data.SqlClient.SqlCommand.SetUpRPCParameters(_SqlRPC rpc, Int32 startCount, Boolean inSchema, SqlParameterCollection parameters)
       at System.Data.SqlClient.SqlCommand.BuildRPC(Boolean inSchema, SqlParameterCollection parameters, _SqlRPC& rpc)
       at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
       at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
       at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
       at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
       at Microsoft.Synchronization.Data.Server.DbServerSyncProvider.GetNewServerAnchor(SyncGroupMetadata groupMetadata, SyncSession session)
       at Microsoft.Synchronization.Data.Server.DbServerSyncProvider.GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession)
       at Service.GetChanges(SyncGroupMetadata groupMetaData, SyncSession syncSession) in C:\AdaptSource\Synchronisation\SynchronisationWebService\Service1.asmx.cs:line 51

     

    -----------------------

    At this point I get the error on the command :

    return _gbaCacheServerSyncProvider.GetChanges(groupMetaData, syncSession);

     

    With the error "InvalidCastException occured"

    Failed to convert parameter value from a DateTime to a Byte[].

     

    I have tried compiling the web service under the following product versions of Microsoft.Synchronization.Data.dll:

    2.0.1215.0

    1.0.1208.0

     

    Thankyou

    Thursday, September 11, 2008 1:29 AM
  •  

    I have not received a follow up regarding this issue :-(  This is a serious problem for me.  The syncing requirement was modified to be able to handel a rather large table with 58 thousand rows and growing, approx 14MB in size by itself.  The unmodified sync method causes 'OutOfMemory' errors on the mobile device itself.  After much reading the correct work around was to introduce 'batching' using a anchor.  Introducing the anchor is what has caused this 'InvalidCastException' error.  Perhaps my code to use this anchor is incorrect?!?!  Any feedback is greatly appreciated as currently the customer has no way of distributing this table to mobile devices.
    Tuesday, September 16, 2008 11:53 PM
  • Can you try replacing all your SqlDbType.Timestamp to SqlDbType.BigInt and try it again?

     

    Wednesday, September 17, 2008 5:04 PM
    Moderator
  • No luck, still errors:

    -System.InvalidCastException---------------------------------
    {"Failed to convert parameter value from a DateTime to a Int64."}
    -Data--------------------------------------------------------
    {System.Collections.ListDictionaryInternal}
    -Inner Exception---------------------------------------------
    {"Invalid cast from 'DateTime' to 'Int64'."}
    -Stack-------------------------------------------------------
       at System.Data.SqlClient.SqlParameter.CoerceValue(Object value, MetaType destinationType)
       at System.Data.SqlClient.SqlParameter.GetCoercedValue()
       at System.Data.SqlClient.SqlParameter.Validate(Int32 index, Boolean isCommandProc)
       at System.Data.SqlClient.SqlCommand.SetUpRPCParameters(_SqlRPC rpc, Int32 startCount, Boolean inSchema, SqlParameterCollection parameters)
       at System.Data.SqlClient.SqlCommand.BuildRPC(Boolean inSchema, SqlParameterCollection parameters, _SqlRPC& rpc)
       at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
       at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
       at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
       at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
       at Microsoft.Synchronization.Data.Server.DbServerSyncProvider.GetNewServerAnchor(SyncGroupMetadata groupMetadata, SyncSession session)
       at Microsoft.Synchronization.Data.Server.DbServerSyncProvider.GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession)
       at Service.GetChanges(SyncGroupMetadata groupMetaData, SyncSession syncSession) in C:\AdaptSource\Synchronisation\SynchronisationWebService\Service1.asmx.cs:line 50

    Friday, September 19, 2008 3:49 AM
  • So you are using a datetime to represent your anchors ? Of the three anchors which particular anchor is this happening for?  In that case did you try to convert them from datetime to a bigint in your query?

     

     

    Sunday, September 21, 2008 12:46 AM
    Moderator
  • Due to time constraints and the urgancy of the issue I have taken over this problem from Christian Findlay.

    The problem has progressed since the last post, I am able to compile/run without errors but now we do not get any rows during the sync.  Can you please examine the code below and provide some insight to where I have gone wrong :

    Web Service -> OnInitialise
    ---------------------------
    {
                this.ApplyChangeFailed += new System.EventHandler<Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs>(AdaptCacheServerSyncProvider_ApplyChangeFailed);
                this.ApplyingChanges += new System.EventHandler<Microsoft.Synchronization.Data.ApplyingChangesEventArgs>(AdaptCacheServerSyncProvider_ApplyingChanges);
                this.ChangesSelected += new System.EventHandler<Microsoft.Synchronization.Data.ChangesSelectedEventArgs>(AdaptCacheServerSyncProvider_ChangesSelected);
                this.ChangesApplied += new System.EventHandler<Microsoft.Synchronization.Data.ChangesAppliedEventArgs>(AdaptCacheServerSyncProvider_ChangesApplied);

                //// Set up stored procedure for sending limited rows
                SqlCommand selectNewAnchorCommand = new SqlCommand();
                selectNewAnchorCommand.Connection = (SqlConnection)this.Connection;
                selectNewAnchorCommand.CommandText = "usp_GetNewBatchAnchor";
                selectNewAnchorCommand.CommandType = CommandType.StoredProcedure;
                selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncLastReceivedAnchor, SqlDbType.DateTime);
                selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncBatchSize, SqlDbType.Int);
                selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncMaxReceivedAnchor, SqlDbType.DateTime).Direction = ParameterDirection.InputOutput;
                selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncNewReceivedAnchor, SqlDbType.DateTime).Direction = ParameterDirection.Output;
                selectNewAnchorCommand.Parameters.Add("@" + SyncSession.SyncBatchCount, SqlDbType.Int).Direction = ParameterDirection.InputOutput;

                this.SelectNewAnchorCommand = selectNewAnchorCommand;

                this.BatchSize = 1000; // Set rows to retrieve in lots of 1000
    }

    SQL -> Stored Procedure
    -----------------------
    CREATE PROCEDURE [dbo].[usp_GetNewBatchAnchor] (
            @sync_last_received_anchor datetime ,
            @sync_batch_size int,
      @sync_max_received_anchor datetime output,
      @sync_new_received_anchor datetime output,   
      @sync_batch_count int output)  
    as           
     if @sync_batch_size <= 0
      set @sync_batch_size = 1000   

     if @sync_max_received_anchor is null
         set @sync_max_received_anchor = min_active_rowversion()-1 

     if @sync_last_received_anchor is null or @sync_last_received_anchor = 0
     begin   
         set @sync_new_received_anchor = @sync_batch_size
      if @sync_batch_count <= 0
       set @sync_batch_count = (CONVERT(timestamp, @sync_max_received_anchor, 120) /  @sync_batch_size) + 1
     end
     else
     begin
         set @sync_new_received_anchor = @sync_last_received_anchor + @sync_batch_size
      if @sync_batch_count <= 0
       set @sync_batch_count = (CONVERT(timestamp, @sync_max_received_anchor, 120) /  @sync_batch_size) - (CONVERT(timestamp, @sync_new_received_anchor, 120) /  @sync_batch_size) + 1
     end
       
        -- check if this is the last batch    
        if @sync_new_received_anchor >= @sync_max_received_anchor
        begin
            set @sync_new_received_anchor = @sync_max_received_anchor       
      if @sync_batch_count <= 0
       set @sync_batch_count = 1
        end     
    go
    ----------------------------------------------------------------

    To recap, we have followed the example posted on the SyncGuru forum for batching and have not had success.  Our code is following the examply fairly strictly, the main change is to use the variable DateTime instead of TimeStamp which caused the initial errors in this post.  Now we just need to understand why we do not get any rows during the sync, I am guessing the stored procedure is not working as intended.

    http://www.syncguru.com/projects/SyncServicesDemoBatching.aspx

    ----------------------------------------------------------------
    I am using Version 2.0.1215.0 of Microsoft Synchronization DLL's
    ----------------------------------------------------------------

     

     

    Thursday, October 9, 2008 6:35 AM
  • Just to verify, perhaps my interpretation of the SyncGuru example is incorrect.  The documentation to add batching to a sync application is brief, all I have done to get this far in batching is :

     

    1. Add the SelectNewAnchorCommand code to the Web Service 'OnInitialise'.

    2. Add a stored procedure to work with the SelectNewAnchorCommand.

     

    Can I get confirmation these steps are at least correct please?  I have got a feeling I have missed a step somewhere.

     

    Monday, October 13, 2008 4:42 AM
  • I would really like to hear from anyone that has gotten batching to work.  The steps they followed, the changelog...

    Omad
    Wednesday, October 29, 2008 4:35 AM
  • To recap the original error that I need resolved :
    -System.InvalidCastException---------------------------------
    {" Invalid cast from 'System.DateTime' to 'System.Byte[]'."}
    -Data--------------------------------------------------------

     

    I can control the data type on the right side of the invalid cast (the TO datatype) to anything I want, however the left side (FROM) is always DateTime.  All I am trying to do is run the example for batching in the following links :
    http://msdn.microsoft.com/en-us/library/bb902828.aspx
    http://www.syncguru.com/projects/SyncServicesDemoBatching.aspx


    My Question :
    How do I fix the invalid cast?
     

     

    I want to change the left side of the invalid cast (the FROM datatype) to be a TimeStamp to work with the examples.  This datatype appears to be defined inside the Sync DLL.

     

    To pick up from the last response :
    So you are using a datetime to represent your anchors ?
    I am trying to use Timestamp like the example used in the MSDN and SyncGuru examples.  The error that started this post has caused me to experiment using different datatypes to represent the anchor, which has proved unsuccessful.

     

    Of the three anchors which particular anchor is this happening for?
    It error's on any of the paramaters (anchors) that are not declared as DateTime.

     

    In that case did you try to convert them from datetime to a bigint in your query?
    It has not called the query yet.  This error occures inside the Synchronization DLL before the SP is called.  The query is only called when all three paramaters are declared as DateTime, but then the SP wont work as intended as it relies on the Timestamp of the row.  In a previous post I showed code that attempts to use DateTime in the SP, however attempts to convert it to/from TimeStamp to function like the examples indicate has not worked.


     

    Monday, November 3, 2008 3:14 AM
  • Hello Christian,


    did you solve your problem? I still have the same problem. I am also using DateTime for CHANGE_DATE and CREATE_DATE, because this was used in the earlier tutorials.
    Now I want to add batching and I am running into problems because I do not have timestamps.


    BUT.... (I think this is your problem too):

    You canNOT convert a datetime to a timestamp and vice versa.

    Because timestamp is NOT the current date. It´s a counter (logical clock) of the database.

    You can check it if you type:


    select CONVERT(datetime, @@DBTS)


    E.g. my result is:

    1900-01-01 00:09:40.333


    So you do not get any results (as you have described) because you wan to retrieve results like:


    SELECT .... WHERE CHANGE_DATE < '1900-01-01 00:09:40.333'



    which gives, of course, no results back :-)

     


    So my general question to all of you:


    Does ANYBODY ever coded a batching with using DateTime instread of timestamps and can give me an example?
    And how do you implement batching with timestamps. I tried to create an example but my MS SQL 2005 database says that I cannot have more than one timestampe column in a database and it seems to me that I need 2 columns (UpdateTimestsamp, InsertTimestamp).


    I have to say that I am really frustrated as I started to use this Sync Framework.
    My solution was build on various tutorials and every "beginner tutorial" works fine but you run into trouble if you want to dive deeper into the framework.

    E.g. first I used INT as PrimaryKey because it was used in the Beginners Tutorial too. Then I found out that I have to use an UniqueID which was easy to solve
    because I am working on a huge database which is used in several installations on various client-systems.

    Now I am having problems again because I used DateTime for CHANGE_DATE, CREATE_DATE and DELETE_DATE like it was shown in various tutorials
    and found out that it seems that I cannot use it when I want to implement batching.


    Maybe you should change your beginners tutorials or add comments or what ever. But it is really frustrating!



    Regards,

    Martin

    Saturday, May 16, 2009 2:09 PM
  • Hi Martin,

    I took over this thread from Christian as I was doing the work / research anyway.

    I too built my application up from the Sync examples and have found its limitations.  You should see all the crazy steps I have to do just to re-build a database structure to work with Identity columns.

    I am under the suspicion my "Failed to convert parameter value" error is because I used the Sync example as my foundation for my application, and not build a fresh application that uses batching from day dot.

    To clarify my problem, I attempted changing the data type passed from sync to the web service, and as you experienced I did not get any rows sync'd for the reason you found.  From what I understand the problem is deep in the Sync DLL that passes the parameter to the web service during execution, it does not seem to convert the data type (that I need to use) to the correct type.

    I am very annoyed I have received no follow up from any forum moderators or the like about this issue.  Its a bug that I dont understand how to fix, and all I am doing is using a standard example and trying to enhance it to use batching.


    Maybe our frustration will attract some attention out there.

    Damian

    P.S.  Someone out there PLEASE PLEASE PLEASE provide a change log and delivery date for the next release of sync.  If batching wont make it in, I would like to know so I can create a crazy work around!!!  (Download a temporary database file via URL to the PocketPC and copy the rows to the main database manually... Yuk)
    Tuesday, May 19, 2009 3:34 AM
  • Hi Omad,

    thanks for your reply. Do you maybe have a Skype-Account so we could exchange our experience?



    Regards,

    Martin
    Tuesday, May 19, 2009 4:28 PM
  • Skype name : master_omad
    Thursday, May 21, 2009 12:24 AM
  • Hi All,

    Did anyone ever get to the bottom of this? I am having exactly the same experience. Basically this is the rough sequence of events for me:

    1. Created new app in VS 2008 with local database cache
    2. Database created and modified fields are of datetime
    3. Tried to implement code from Microsoft and SyncGuru which does batching. Both of these use timestamp, not DateTime fields from what I can see
    4. Got the "Failed to convert parameter value from a DateTime to a Byte[]" error message
    5. Tried to change all my code to Timestamp (except the actual server SQL fields - used CONVERT when reading in the new SyncAnchor command)
    6. Could not get it to work

    So then I tried changing everything to DateTime, including the SyncGuru / Microsoft code, but now I don't get any data downloaded at all, but no errors either.

    If you came across a solution, please let me know :-)

    Thanks!
    Monday, July 13, 2009 4:30 AM
  • Please try change the parameter data type -

    SqlDbType.Timestamp of "@"
    + SyncSession.SyncNewReceivedAnchor, SqlDbType.Timestamp).Direction = ParameterDirection.Output;

    to SqlDbType.Datetime

    Thanks.


    Leo Zhou ------ This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, July 29, 2009 6:33 PM
    Answerer
  • Hi there!

    Thanks very much for your reply, unfortunately it was too late for me. What I did instead was to send parameters through during the sync, and then did a partial sync of data (in effect hard-coded batching) using those parameters.

    I must admit, coming from a Lotus Notes development background meant that my expectations were that it should be easier, but live and learn!

    My blog post on this: http://blog.geoscope.com.au/2009/07/sync-framework-batching.html
    Friday, July 31, 2009 1:49 AM
  • L Zhou :  If you read my post on Thursday October 9th, 2008 (or Edgeman's post for that matter) you would have noticed we tried the datatype DateTime but it returned no data.  Its pretty self explanatory when an error tells you it cannot convert "From DateTime to [?] format" that the next step would be to try DateTime.  FrUsTrAtIoN!  No HaIr LeFt!!!

    One more time.
    My understanding of this mess so far :

    1.  The Batching 'TimeStamp' sent from the sync Client to the sync Server is a "Virtual TimeStamp".  This "Virtual Timestamp" is used to keep track of the row number using sync's internal tracking.  This is not a real date or time, hence has no real relationship with a row on the database, but is a counter for sync to keep track of during the session.

    2.  Converting the parameter to 'DateTime' results in no rows getting sync'd.  In the post (Thursday October 9th, 2008) you will see that I attempt to convert the parameters in my SQL.  After looking into how the SQL works and the actual values of the 'DateTime' you will see that this SQL will never find any rows to retrieve.

    3.  THIS THREAD was started because 'GetChanges' command is internally converting the paramater into something else.  I find it amazing that all I seem to get asked is to work around the original problem.  How about someone look at the line of code in 'GetChanges' tell me what my stack trace revealed.

    4.  I will happily provide my program for you step through if necessary.

    Edgeman :  Thankyou for your blog.  Banging your had against Batching does hurt.
    Wednesday, August 5, 2009 12:43 AM