为什么我必须复制我的代码来处理两个同步的 MSSQL 数据库
Why do I have to duplicate my code to handle two synced MSSQL databases
我正在编写一个应用程序,具有 SQL 服务器连接。这种连接不是很稳定,所以我决定使用 Microsoft Sync Framework,它非常好。
我的问题是,当我在本地和服务器数据库之间切换时,我必须使用两倍的数据集和表适配器,而且我必须更改所有 winform 数据源(例如:组合框)。
我想实现的是在两个数据库之间轻松切换。
我有一个完整的工作代码,但我认为它可以更好。
初始化代码:
int timeout = 5;
public Form1()
{
Program.ChangeConnectionString("TESTDBConnectionString", "Data Source=ip\engine;Initial Catalog=TESTDB;Persist Security Info=True;User ID=usr;Password=psw; Connect Timeout = " + timeout);
Program.ChangeConnectionString("localConnectionString", "Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = \local.mdf; Integrated Security = True; Connect Timeout = " + timeout);
InitializeComponent();
}
更新(和连接检查)代码:
private void UpdateDB()
{
CheckServer();
this.tbl_SyncTestTableAdapter1.Fill(this.localDataSet1.tbl_SyncTest);
if (Program.IsOnline)
{
this.tbl_SyncTestTableAdapter.Fill(this.tESTDBDataSet.tbl_SyncTest);
tblSyncTestBindingSource.DataSource = tESTDBDataSet.tbl_SyncTest;
tblSyncTestBindingSource1.DataSource = tESTDBDataSet.tbl_SyncTest;
tblSyncTestBindingSource2.DataSource = tESTDBDataSet.tbl_SyncTest;
tblSyncTestBindingSource4.DataSource = tESTDBDataSet.tbl_SyncTest;
dataGridView2.Visible = true;
Sync();
}
else
{
tblSyncTestBindingSource.DataSource = localDataSet1.tbl_SyncTest;
tblSyncTestBindingSource1.DataSource = localDataSet1.tbl_SyncTest;
tblSyncTestBindingSource2.DataSource = localDataSet1.tbl_SyncTest;
tblSyncTestBindingSource4.DataSource = localDataSet1.tbl_SyncTest;
dataGridView2.Visible = false;
label8.Text = "OFFLINE";
}
}
示例数据库操作:
private void button3_Click(object sender, EventArgs e)
{
string[] val = new string[] { comboBox2.Text, textBox5.Text, textBox4.Text };
int ival = (int)comboBox2.SelectedValue;
CheckServer();
if (Program.IsOnline) tbl_SyncTestTableAdapter.Update(val[0], val[1], val[2], ival);
else tbl_SyncTestTableAdapter1.Update(val[0], val[1], val[2], ival);
UpdateDB();
}
如果您需要更多代码,请告诉我,但我认为其他代码无关紧要。
编辑,同步代码:
private void Sync()
{
label8.Text = "SYNCING...";
new Task(() =>
{
ProvisionServer();
ProvisionLocal();
SqlConnection serverConn = new SqlConnection(Properties.Settings.Default["TESTDBConnectionString"].ToString());
SqlConnection localConn = new SqlConnection(Properties.Settings.Default["localConnectionString"].ToString());
SyncOrchestrator syncOrchestrator = new SyncOrchestrator();
syncOrchestrator.LocalProvider = new SqlSyncProvider("TestScope", localConn);
syncOrchestrator.RemoteProvider = new SqlSyncProvider("TestScope", serverConn);
syncOrchestrator.Direction = SyncDirectionOrder.DownloadAndUpload;
SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();
Console.WriteLine("Start Time: " + syncStats.SyncStartTime);
Console.WriteLine("Total Changes Uploaded: " + syncStats.UploadChangesTotal);
Console.WriteLine("Total Changes Downloaded: " + syncStats.DownloadChangesTotal);
Console.WriteLine("Complete Time: " + syncStats.SyncEndTime);
Console.WriteLine(String.Empty);
this.BeginInvoke((Action)(() =>
{
label8.Text = "SYNCED";
this.tbl_SyncTestTableAdapter.Fill(this.tESTDBDataSet.tbl_SyncTest);
this.tbl_SyncTestTableAdapter1.Fill(this.localDataSet1.tbl_SyncTest);
}));
}).Start();
}
存在 DataAdapter
模式,因此您可以 Adapt
针对不同的场景,而不必 implement/duplicate 在整个应用程序中使用相同的逻辑。在您的情况下,您只对选择正确的适配器实现感兴趣。
如果这是您唯一的表单,您可以引入一个 属性 来获取适当的 DataAdapter 并在整个过程中使用它。
// Adapter will give you an interface
// to either your local store
// or your online store
private IDataAdapter Adapter
{
get
{
IDataAdapter _adapter = null;
CheckServer();
if (Program.IsOnline)
{
_adapter = new SqlDataAdapter(selectcommand, onlineconnection);
}
else
{
_adapter = new SqlCeDataAdapter(selectCommand, offlineConnection);
}
return _adapter
}
}
您的其他方法只能处理一个数据集:
private void UpdateDB()
{
this.Adapter.Fill(this.localDataSet1);
// you don't need to change any bindings ...
}
以及您的数据库操作:
private void button3_Click(object sender, EventArgs e)
{
string[] val = new string[] { comboBox2.Text, textBox5.Text, textBox4.Text };
// if the Adapter has changed here
// the dataset might hold different states
// so it might hold on Update where an Insert is needed
// in that case use some logic to Fill a new Dataset and merge that
// with the current one
this.Adapter.Update(this.localDataSet1); // the values from the dataset will be stored.
}
但是既然你已经公开了你的同步代码,你为什么不直接总是连接到你的本地数据库,然后让同步框架处理updates/inserts 在本地和中央数据库中都需要。将在线和离线场景的逻辑带到您选择 DataAdapter 的地方首先违背了同步框架的目的。
我正在编写一个应用程序,具有 SQL 服务器连接。这种连接不是很稳定,所以我决定使用 Microsoft Sync Framework,它非常好。 我的问题是,当我在本地和服务器数据库之间切换时,我必须使用两倍的数据集和表适配器,而且我必须更改所有 winform 数据源(例如:组合框)。
我想实现的是在两个数据库之间轻松切换。 我有一个完整的工作代码,但我认为它可以更好。
初始化代码:
int timeout = 5;
public Form1()
{
Program.ChangeConnectionString("TESTDBConnectionString", "Data Source=ip\engine;Initial Catalog=TESTDB;Persist Security Info=True;User ID=usr;Password=psw; Connect Timeout = " + timeout);
Program.ChangeConnectionString("localConnectionString", "Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = \local.mdf; Integrated Security = True; Connect Timeout = " + timeout);
InitializeComponent();
}
更新(和连接检查)代码:
private void UpdateDB()
{
CheckServer();
this.tbl_SyncTestTableAdapter1.Fill(this.localDataSet1.tbl_SyncTest);
if (Program.IsOnline)
{
this.tbl_SyncTestTableAdapter.Fill(this.tESTDBDataSet.tbl_SyncTest);
tblSyncTestBindingSource.DataSource = tESTDBDataSet.tbl_SyncTest;
tblSyncTestBindingSource1.DataSource = tESTDBDataSet.tbl_SyncTest;
tblSyncTestBindingSource2.DataSource = tESTDBDataSet.tbl_SyncTest;
tblSyncTestBindingSource4.DataSource = tESTDBDataSet.tbl_SyncTest;
dataGridView2.Visible = true;
Sync();
}
else
{
tblSyncTestBindingSource.DataSource = localDataSet1.tbl_SyncTest;
tblSyncTestBindingSource1.DataSource = localDataSet1.tbl_SyncTest;
tblSyncTestBindingSource2.DataSource = localDataSet1.tbl_SyncTest;
tblSyncTestBindingSource4.DataSource = localDataSet1.tbl_SyncTest;
dataGridView2.Visible = false;
label8.Text = "OFFLINE";
}
}
示例数据库操作:
private void button3_Click(object sender, EventArgs e)
{
string[] val = new string[] { comboBox2.Text, textBox5.Text, textBox4.Text };
int ival = (int)comboBox2.SelectedValue;
CheckServer();
if (Program.IsOnline) tbl_SyncTestTableAdapter.Update(val[0], val[1], val[2], ival);
else tbl_SyncTestTableAdapter1.Update(val[0], val[1], val[2], ival);
UpdateDB();
}
如果您需要更多代码,请告诉我,但我认为其他代码无关紧要。
编辑,同步代码:
private void Sync()
{
label8.Text = "SYNCING...";
new Task(() =>
{
ProvisionServer();
ProvisionLocal();
SqlConnection serverConn = new SqlConnection(Properties.Settings.Default["TESTDBConnectionString"].ToString());
SqlConnection localConn = new SqlConnection(Properties.Settings.Default["localConnectionString"].ToString());
SyncOrchestrator syncOrchestrator = new SyncOrchestrator();
syncOrchestrator.LocalProvider = new SqlSyncProvider("TestScope", localConn);
syncOrchestrator.RemoteProvider = new SqlSyncProvider("TestScope", serverConn);
syncOrchestrator.Direction = SyncDirectionOrder.DownloadAndUpload;
SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();
Console.WriteLine("Start Time: " + syncStats.SyncStartTime);
Console.WriteLine("Total Changes Uploaded: " + syncStats.UploadChangesTotal);
Console.WriteLine("Total Changes Downloaded: " + syncStats.DownloadChangesTotal);
Console.WriteLine("Complete Time: " + syncStats.SyncEndTime);
Console.WriteLine(String.Empty);
this.BeginInvoke((Action)(() =>
{
label8.Text = "SYNCED";
this.tbl_SyncTestTableAdapter.Fill(this.tESTDBDataSet.tbl_SyncTest);
this.tbl_SyncTestTableAdapter1.Fill(this.localDataSet1.tbl_SyncTest);
}));
}).Start();
}
存在 DataAdapter
模式,因此您可以 Adapt
针对不同的场景,而不必 implement/duplicate 在整个应用程序中使用相同的逻辑。在您的情况下,您只对选择正确的适配器实现感兴趣。
如果这是您唯一的表单,您可以引入一个 属性 来获取适当的 DataAdapter 并在整个过程中使用它。
// Adapter will give you an interface
// to either your local store
// or your online store
private IDataAdapter Adapter
{
get
{
IDataAdapter _adapter = null;
CheckServer();
if (Program.IsOnline)
{
_adapter = new SqlDataAdapter(selectcommand, onlineconnection);
}
else
{
_adapter = new SqlCeDataAdapter(selectCommand, offlineConnection);
}
return _adapter
}
}
您的其他方法只能处理一个数据集:
private void UpdateDB()
{
this.Adapter.Fill(this.localDataSet1);
// you don't need to change any bindings ...
}
以及您的数据库操作:
private void button3_Click(object sender, EventArgs e)
{
string[] val = new string[] { comboBox2.Text, textBox5.Text, textBox4.Text };
// if the Adapter has changed here
// the dataset might hold different states
// so it might hold on Update where an Insert is needed
// in that case use some logic to Fill a new Dataset and merge that
// with the current one
this.Adapter.Update(this.localDataSet1); // the values from the dataset will be stored.
}
但是既然你已经公开了你的同步代码,你为什么不直接总是连接到你的本地数据库,然后让同步框架处理updates/inserts 在本地和中央数据库中都需要。将在线和离线场景的逻辑带到您选择 DataAdapter 的地方首先违背了同步框架的目的。