Recently, we have created a project for regular synchronization of distributed databases. That is to say, databases on multiple physical nodes need to synchronize table data at some time every day, changes (increments) to a table on a specified node can be recorded by executing sqlcommand on the table. When the synchronization process occurs, execute the same sqlcommand on the same table on all other nodes. Because synchronization occurs on a regular basis, incremental sqlcommand needs to be saved first. At first, we plan to serialize it and save it in the database. But at runtime, the problem arises, sqlcommand cannot be serialized !!! All classes inherited from idbcommand cannot be serialized, and all implementation classes inherited from idbparameter cannot be serialized.
We did not expect this problem at the beginning. It seems that we should properly solve this problem. Otherwise, we must make a lot of modifications to our design and implementation! The final solution we adopt is to manually write a serializable esqlcommand, which can be converted to sqlcommand, just like this:
Sqlcommand command = New Sqlcommand ( This . Plain text, New Sqlconnection (connstr ), Null );
// Forward
Esqlcommand escommand = New Esqlcommand (command );
// Reverse
Sqlcommand command2 = Escommand. tosqlcommand (connstr );
With esqlcommand, our design almost does not need to be modified. We only need to convert it to esqlcommand before the incremental serialization is saved to the database, and then read the incremental field deserialization before converting it to sqlcommand.
The implementation of esqlcommand is given below (of course, it is inevitable to include the serializable esqlparameter implementation ):
# Region Esqlcommand
/// <Summary>
/// Sqlcommand that can be serialized by esqlcommand. System. Data. sqlclient. sqlcommand cannot be serialized.
/// </Summary>
[Serializable]
Public Class Esqlcommand
{
Private Esqlparameter [] Esparas;
Private String Plain text;
Private Commandtype primitive type;
PublicEsqlcommand (sqlcommand command)
{
This. Plain text=Command. commandtext;
This. Category Type=Command. commandtype;
This . Esparas = New Esqlparameter [command. Parameters. Count];
Int Index = 0 ;
Foreach (Sqlparameter para In Command. Parameters)
{
This . Esparas [Index] = New Esqlparameter (para );
Index ++ ;
}
}
Public Sqlcommand tosqlcommand ( String Connstr)
{
Sqlcommand command = New Sqlcommand ( This . Plain text, New Sqlconnection (connstr ), Null );
For ( Int I = 0 ; I < This . Esparas. length; I ++ )
{
Command. Parameters. Add ( This . Esparas [I]. tosqlparameter ());
}
Command. commandtype = This . Struct type;
Return Command;
}
}
[Serializable]
Public Class Esqlparameter
{
Public Esqlparameter (sqlparameter spara)
{
This . Paraname = Spara. parametername;
This . Paralen = Spara. size;
This . Paraval = Spara. value;
This . Sqldbtype = Spara. sqldbtype;
}
Public Sqlparameter tosqlparameter ()
{
Sqlparameter para = New Sqlparameter ( This . Paraname, This . Sqldbtype, This . Paralen );
Para. Value = This . Paraval;
ReturnPara;
}
# Region Paraname
Private String Paraname = "" ;
Public String Paraname
{
Get
{
Return This . Paraname;
}
Set
{
This . Paraname = Value;
}
}
# Endregion
# Region Paralen
Private Int Paralen = 0 ;
Public Int Paralen
{
Get
{
Return This . Paralen;
}
Set
{
This . Paralen = Value;
}
}
# Endregion
# Region Paraval
Private Object Paraval = Null ;
Public Object Paraval
{
Get
{
Return This . Paraval;
}
Set
{
This . Paraval = Value;
}
}
# Endregion
# Region Sqldbtype
Private Sqldbtype = Sqldbtype. nvarchar;
Public Sqldbtype
{
Get
{
Return This . Sqldbtype;
}
Set
{
This . Sqldbtype = Value;
}
}
# Endregion
}
# Endregion