Vorgehensweise: Asynchrones Synchronisieren von Daten (programmgesteuert)
In diesem Thema erfahren Sie, wie ein Abonnement mithilfe der SqlCeReplication-Klasse asynchron synchronisiert werden kann. Die asynchrone Datensynchronisierung ermöglicht es, dass die Anwendung während der Synchronisierung andere Aktionen ausführt. Weitere Informationen zum Verwenden des SqlServerCe-Namespaces finden Sie in der Referenzdokumentation zum SqlServerCe-Namespace.
So starten Sie die asynchrone Datensynchronisierung
Initialisieren Sie ein SqlCeReplication-Objekt. Sie müssen das Objekt außerhalb aller Methoden deklarieren, damit der Zugriff auf das Objekt möglich ist.
private SqlCeReplication repl;
Erstellen Sie innerhalb der Methode, die die Synchronisierung startet, eine Instanz des SqlCeReplication-Objekts, und legen Sie dann die Eigenschaften fest, die für die Synchronisierung mit einem Verleger benötigt werden.
this.repl = new SqlCeReplication(); repl.InternetUrl = "https://www.adventure-works.com/sqlmobile/sqlcesa30.dll"; repl.InternetLogin = "MyInternetLogin"; repl.InternetPassword = "<password>"; repl.Publisher = "MyPublisher"; repl.PublisherDatabase = "MyPublisherDatabase"; repl.PublisherLogin = "MyPublisherLogin"; repl.PublisherPassword = "<password>"; repl.Publication = "MyPublication"; repl.Subscriber = "MySubscriber"; repl.SubscriberConnectionString = "Data Source=MyDatabase.sdf";
Rufen Sie die BeginSynchronize-Methode auf. Hierdurch wird das IAsyncResult-Objekt zurückgegeben. Wenn Sie BeginSynchronize aufrufen, müssen Sie einen AsyncCallback-Ereignishandler und das SqlCeReplication-Objekt übergeben. Das AsyncCallback-Ereignis wird ausgelöst, wenn die Synchronisierung abgeschlossen ist. Sie können zudem Ereignishandler für die Ereignisse OnStartTableUpload, OnStartTableDownload und OnSynchronization übergeben.
IAsyncResult ar = repl.BeginSynchronize(new AsyncCallback(this.SyncCompletedCallback), new OnStartTableUpload(this.OnStartTableUploadCallback), new OnStartTableDownload(this.OnStartTableDownloadCallback), new OnSynchronization(this.OnSynchronizationCallback), repl);
So werden Synchronisierungsereignisse verarbeitet
AsyncCallback ist das einzige erforderliche Ereignis. Sein einziger Parameter ist IAsyncResult.
public void SyncCompletedCallback(IAsyncResult ar) { ... }
Die Ereignishandler für OnStartTableUpload und OnStartTableDownload verwenden beide IAsyncResult und den Tabellennamen (in Form einer Zeichenfolge) als Parameter.
public void OnStartTableUploadCallback(IAsyncResult ar, string tableName) { ... } public void OnStartTableDownloadCallback(IAsyncResult ar, string tableName) { ... }
Der OnSynchronization-Ereignishandler verwendet IAsyncResult und eine ganze Zahl als Parameter, die den Prozentsatz der abgeschlossenen Synchronisierung darstellt.
public void OnSynchronizationCallback(IAsyncResult ar, int percentComplete) { ... }
So beenden Sie die asynchrone Datensynchronisierung
Verwenden Sie innerhalb des AsyncCallback-Ereignishandlers die übergebenen Objekte SqlCeReplication und IAsyncResult, um die EndSynchronize-Methode aufzurufen.
SqlCeReplication repl = (SqlCeReplication)ar.AsyncState; repl.EndSynchronize(ar);
Beispiel
In dem folgenden Beispiel wird gezeigt, wie die asynchrone Datensynchronisierung implementiert wird. In dem Beispiel wird SyncStatus verwendet, um die Benutzeroberfläche während der Synchronisierung zu aktualisieren und den Benutzer auf diese Weise über den Synchronisierungsstatus zu informieren. Die Benutzeroberfläche wird aktualisiert, sobald ein Synchronisierungsereignis ausgelöst wird und sobald eine Tabelle geuploadet oder gedownloadet wird. Wenn die Synchronisierung abgeschlossen ist, ruft die Anwendung den Zeitpunkt der letzten erfolgreichen Synchronisierung aus der __sysMergeSubscriptions-Tabelle ab und zeigt die Ergebnisse an.
public class MyForm : Form
{
private string tableName;
private int percentage;
private SyncStatus eventStatus;
private SqlCeReplication repl;
private EventHandler myUserInterfaceUpdateEvent;
internal enum SyncStatus
{
PercentComplete,
BeginUpload,
BeginDownload,
SyncComplete
}
public MyForm()
{
// InitializeComponent();
this.myUserInterfaceUpdateEvent = new EventHandler(MyUserInterfaceUpdateEvent);
}
public void MyUserInterfaceUpdateEvent(object sender, System.EventArgs e)
{
switch (this.eventStatus)
{
case SyncStatus.BeginUpload:
//this.labelStatusValue.Text = "Began uploading table : " + tableName;
break;
case SyncStatus.PercentComplete:
//this.labelStatusValue.Text = "Sync with SQL Server is " + percentage.ToString() + "% complete.";
break;
case SyncStatus.BeginDownload:
//this.labelStatusValue.Text = "Began downloading table : " + tableName;
break;
case SyncStatus.SyncComplete:
//this.labelStatusValue.Text = "Synchronization has completed successfully";
//this.labelLastSyncValue.Text = GetLastSuccessfulSyncTime().ToString();
break;
}
}
public void SyncCompletedCallback(IAsyncResult ar)
{
try
{
SqlCeReplication repl = (SqlCeReplication)ar.AsyncState;
repl.EndSynchronize(ar);
repl.SaveProperties();
this.eventStatus = SyncStatus.SyncComplete;
}
catch (SqlCeException e)
{
MessageBox.Show(e.Message);
}
finally
{
// NOTE: If you want to set Control properties from within this
// method, you must use Control.Invoke method to marshal
// the call to the UI thread; otherwise you might deadlock your
// application; See Control.Invoke documentation for more information
//
this.Invoke(this.myUserInterfaceUpdateEvent);
}
}
public void OnStartTableUploadCallback(IAsyncResult ar, string tableName)
{
this.tableName = tableName;
this.eventStatus = SyncStatus.BeginUpload;
// NOTE: If you want to set Control properties from within this
// method, you must use Control.Invoke method to marshal
// the call to the UI thread; otherwise you might deadlock your
// application; See Control.Invoke documentation for more information
//
this.Invoke(this.myUserInterfaceUpdateEvent);
}
public void OnSynchronizationCallback(IAsyncResult ar, int percentComplete)
{
this.percentage = percentComplete;
this.eventStatus = SyncStatus.PercentComplete;
// NOTE: If you want to set Control properties from within this
// method, you must use Control.Invoke method to marshal
// the call to the UI thread; otherwise you might deadlock your
// application; See Control.Invoke documentation for more information
//
this.Invoke(this.myUserInterfaceUpdateEvent);
}
public void OnStartTableDownloadCallback(IAsyncResult ar, string tableName)
{
this.tableName = tableName;
this.eventStatus = SyncStatus.BeginDownload;
// NOTE: If you want to set Control properties from within this
// method, you must use Control.Invoke method to marshal
// the call to the UI thread; otherwise you might deadlock your
// application; See Control.Invoke documentation for more information
//
this.Invoke(this.myUserInterfaceUpdateEvent);
}
private void ButtonSynchronize_Click(object sender, System.EventArgs e)
{
try
{
this.repl = new SqlCeReplication();
repl.SubscriberConnectionString = "Data Source=Test.sdf";
if (false == File.Exists("Test.sdf"))
{
repl.AddSubscription(AddOption.CreateDatabase);
repl.PublisherSecurityMode = SecurityType.DBAuthentication;
repl.Publisher = "MyPublisher";
repl.PublisherLogin = "PublisherLogin";
repl.PublisherPassword = "<Password>";
repl.PublisherDatabase = "AdventureWorksDW";
repl.Publication = "AdventureWorksDW";
repl.InternetUrl = "https://www.adventure-works.com/sqlmobile/sqlcesa30.dll";
repl.InternetLogin = "MyInternetLogin";
repl.InternetPassword = "<Password";
repl.Subscriber = "MySubscriber";
}
else
{
repl.LoadProperties();
}
IAsyncResult ar = repl.BeginSynchronize(
new AsyncCallback(this.SyncCompletedCallback),
new OnStartTableUpload(this.OnStartTableUploadCallback),
new OnStartTableDownload(this.OnStartTableDownloadCallback),
new OnSynchronization(this.OnSynchronizationCallback),
repl);
}
catch (SqlCeException ex)
{
MessageBox.Show(ex.Message);
}
}
public DateTime GetLastSuccessfulSyncTime()
{
DateTime localDateTime;
SqlCeConnection conn = null;
SqlCeCommand cmd = null;
try
{
conn = new SqlCeConnection("Data Source = Test.sdf");
conn.Open();
cmd = conn.CreateCommand();
cmd.CommandText = "SELECT LastSuccessfulSync FROM __sysMergeSubscriptions " +
"WHERE Publication=@publication";
cmd.Parameters.Add("@publication", SqlDbType.NVarChar, 4000);
cmd.Parameters["@publication"].Value = "AdventureWorksDW";
//Note: LastSuccessfulSync is stored in local time, not UTC time
localDateTime = (DateTime)cmd.ExecuteScalar();
return localDateTime;
}
finally
{
conn.Close();
}
}
}
Public Class MyForm
Inherits Form
Private myUserInterfaceUpdateEvent As EventHandler
Private tableName As String
Private percentage As Integer
Private eventStatus As SyncStatus
Private repl As SqlCeReplication
Friend Enum SyncStatus
PercentComplete
BeginUpload
BeginDownload
SyncComplete
End Enum 'SyncStatus
Public Sub New()
' InitializeComponent();
Me.myUserInterfaceUpdateEvent = New EventHandler(AddressOf UserInterfaceUpdateEvent)
End Sub 'New
Public Sub UserInterfaceUpdateEvent(ByVal sender As Object, ByVal e As System.EventArgs)
Select Case Me.eventStatus
Case SyncStatus.BeginUpload
'this.labelStatusValue.Text = "Began uploading table : " & tableName;
Case SyncStatus.PercentComplete
'this.labelStatusValue.Text = "Sync with SQL Server is " & percentage.ToString() & "% complete.";
Case SyncStatus.BeginDownload
'this.labelStatusValue.Text = "Began downloading table : " & tableName;
Case SyncStatus.SyncComplete
'this.labelStatusValue.Text = "Synchronization has completed successfully";
'this.labelLastSyncValue.Text = GetLastSuccessfulSyncTime().ToString();
End Select
End Sub 'UserInterfaceUpdateEvent
Public Sub SyncCompletedCallback(ByVal ar As IAsyncResult)
Try
Dim repl As SqlCeReplication = CType(ar.AsyncState, SqlCeReplication)
repl.EndSynchronize(ar)
repl.SaveProperties()
Me.eventStatus = SyncStatus.SyncComplete
Catch e As SqlCeException
MessageBox.Show(e.Message)
Finally
' NOTE: If you want to set Control properties from within this
' method, you must use Control.Invoke method to marshal
' the call to the UI thread; otherwise you might deadlock your
' application; See Control.Invoke documentation for more information
'
Me.Invoke(Me.myUserInterfaceUpdateEvent)
End Try
End Sub 'SyncCompletedCallback
Public Sub OnStartTableUploadCallback(ByVal ar As IAsyncResult, ByVal tableName As String)
Me.tableName = tableName
Me.eventStatus = SyncStatus.BeginUpload
' NOTE: If you want to set Control properties from within this
' method, you must use Control.Invoke method to marshal
' the call to the UI thread; otherwise you might deadlock your
' application; See Control.Invoke documentation for more information
'
Me.Invoke(Me.myUserInterfaceUpdateEvent)
End Sub 'OnStartTableUploadCallback
Public Sub OnSynchronizationCallback(ByVal ar As IAsyncResult, ByVal percentComplete As Integer)
Me.percentage = percentComplete
Me.eventStatus = SyncStatus.PercentComplete
' NOTE: If you want to set Control properties from within this
' method, you must use Control.Invoke method to marshal
' the call to the UI thread; otherwise you might deadlock your
' application; See Control.Invoke documentation for more information
'
Me.Invoke(Me.myUserInterfaceUpdateEvent)
End Sub 'OnSynchronizationCallback
Public Sub OnStartTableDownloadCallback(ByVal ar As IAsyncResult, ByVal tableName As String)
Me.tableName = tableName
Me.eventStatus = SyncStatus.BeginDownload
' NOTE: If you want to set Control properties from within this
' method, you must use Control.Invoke method to marshal
' the call to the UI thread; otherwise you might deadlock your
' application; See Control.Invoke documentation for more information
'
Me.Invoke(Me.myUserInterfaceUpdateEvent)
End Sub 'OnStartTableDownloadCallback
Private Sub ButtonSynchronize_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Try
Me.repl = New SqlCeReplication()
repl.SubscriberConnectionString = "Data Source=Test.sdf"
If False = File.Exists("Test.sdf") Then
repl.AddSubscription(AddOption.CreateDatabase)
repl.PublisherSecurityMode = SecurityType.DBAuthentication
repl.Publisher = "MyPublisher"
repl.PublisherLogin = "PublisherLogin"
repl.PublisherPassword = "<Password>"
repl.PublisherDatabase = "AdventureWorksDW"
repl.Publication = "AdventureWorksDW"
repl.InternetUrl = "https://www.adventure-works.com/sqlmobile/sqlcesa30.dll"
repl.InternetLogin = "InternetLogin"
repl.InternetPassword = "<Password>"
repl.Subscriber = "MySubscriber"
Else
repl.LoadProperties()
End If
Dim ar As IAsyncResult = repl.BeginSynchronize( _
New AsyncCallback(AddressOf Me.SyncCompletedCallback), _
New OnStartTableUpload(AddressOf Me.OnStartTableUploadCallback), _
New OnStartTableDownload(AddressOf Me.OnStartTableDownloadCallback), _
New OnSynchronization(AddressOf Me.OnSynchronizationCallback), repl)
Catch ex As SqlCeException
MessageBox.Show(ex.Message)
End Try
End Sub 'ButtonSynchronize_Click
Public Function GetLastSuccessfulSyncTime() As DateTime
Dim localDateTime As DateTime
Dim conn As SqlCeConnection = Nothing
Dim cmd As SqlCeCommand = Nothing
Try
conn = New SqlCeConnection("Data Source = Test.sdf")
conn.Open()
cmd = conn.CreateCommand()
cmd.CommandText = "SELECT LastSuccessfulSync FROM __sysMergeSubscriptions " & _
"WHERE Publication=@publication"
cmd.Parameters.Add("@publication", SqlDbType.NVarChar, 4000)
cmd.Parameters("@publication").Value = "AdventureWorksDW"
'Note: LastSuccessfulSync is stored in local time, not UTC time
localDateTime = CType(cmd.ExecuteScalar(), DateTime)
Return localDateTime
Finally
conn.Close()
End Try
End Function 'GetLastSuccessfulSyncTime
End Class 'MyForm
Siehe auch
Konzepte
Asynchrone Datensynchronisierung
Verwenden der Mergereplikation