基于微软Synchronization Services双向同步技术在企业项目中的架构应用研究

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
简介:
项目应用场景:
 
      某客户是一个大型集团企业的信息部门,掌管着企业几百台服务器,并且以后会不断扩充;
   为了更好的维护信息办的服务器;信息部门需要开发一套维护系统,来记录各个服务器的相关状态信息
(如, IP 、所安装在服务器的应用系统和相关信息等),便于维护和查询;客户维护人员可以携带笔记本 脱机即时编写维修服务器相关记录信息(增、删、查、改),客户端联网即可自动同步到服务器最新维护数据。 
      客户要求实现服务器端和客户端双向同步的方式,客户端操作数据服务器端自动更新,反之操作服务器端,
    客户端自动更新。
 
早先的解决方案:
客户端和服务端都使用SQL2005数据库,并采用数据库订阅的方式进行数据同步。
此种设计缺点是:

      1、客户端必须安装SQL2005(包括SQL Server Express),造成操作客户端系统运行速度降低,占用客户端计算机系统资源大等问题。
      2、同步方式配置复杂。需要订阅方式发布服务器和订阅服务器互相注册,服务器端与客户端配置复杂。
最新的解决方案:
      1、客户端数据库采用微软Microsoft SQL Server Compact 3.5压缩数据库,实施技术Microsoft Synchronization Services v1.0。
      2、服务器端数据库采用微软Microsoft SQL Server 2005(2008)。
      3、开发工具是Microsoft Visual Studio 2008正式版。
      服务器端开发B/S维护系统;C/S端开发客户端Winform(WPF)应用程序;实现客户端winform系统业务操作会相应的同步到服务器中;反之,服务器端的业务系统操作也会自动同步到下属不同的客户端Compact数据库中。

 
     架构设计:
     1、服务器端系统架构设计采用MVPC架构:Web Client Software Factory
     2、客户端业务系统架构设计也MVPC架构:Smart Client Software Factory
     优点:客户端模块代码很容易移植到服务器端asp.net开发的业务系统;解决客户端与服务器端应用模块重复,减少代码量;

如果采用Microsoft SQL Server Compact 3.5客户端数据库(Sdf扩展名的数据库文件),不必安装Microsoft SQL Server 2005数据库,客户只需要一个安装包,即可实现客户端的应用系统安装,更加方便灵活的用户体验。

 
 Sync Services for ADO.NET provider 技术应用场景

    * C\S结构的离线应用,在本地缓存中心数据库中的部分数据(极特别的情况下会缓存全部)。应用程序使用缓存的数据,并在特定的时间把一批更改上次到中心数据库。

    * 协作应用,应用程序只使用本地数据,并周期性的与其他参与者进行 Peer-to-Peer 的同步。数据库双向同步:Feature实现客户端C/S系统数据库数据与服务器端B/S管理系统数据库数据进行数据双向同步;

Use case:用户在客户端针对本地数据库系统进行增加、删除、修改等操作,如果在线联网状态,数据自动同步到远程SQL Server数据库;有管理权限用户,登录B/S系统进行增加、删除、修改等操作,SQL Server数据自动同步到客户端数据库。

功能实现Server与Client端进行数据操作(增加、删除),都能很好的进行数据双向同步;

Sync Demo源码程序截图如下:


Compact数据库同步技术功能

Microsoft SQL Server Compact 3.5 (以前称为 Microsoft SQL Server 2005 Mobile Edition)是一种压缩数据库,很适合嵌入到移动应用程序和桌面应用程序中。Microsoft SQL Server Compact 3.5 为开发本机和托管应用程序的开发人员提供了与其他 SQL Server 版本通用的编程模型。SQL Server Compact Edition 以很少的空间占用提供关系数据库功能:健壮数据存储、优化查询处理器以及可靠、可缩放的连接。 
Microsoft Synchronization Services for ADO.NET 是一组 DLL,提供了一个可组构的 API。根据应用程序的体系结构和要求,可以使用提供的所有或部分组件。
 
Synchronization Services 实现了 SQL Server Compact 3.5 客户端数据库和服务器数据库或任何其他数据源(如以 XML 形式提供股票报价的服务)之间的同步。在同步两个数据库方面,Synchronization Services 支持使用为之提供了 ADO.NET 提供程序的任何服务器数据库的双层和 N 层体系结构。

在对客户端数据库和其他类型的数据源进行同步方面,Synchronization Services 支持基于服务的体系结构。与双层或 N 层体系结构相比,此体系结构需要编写更多的应用程序代码;但是,它不需要开发人员采取另一种不同的方式进行同步。

通过 Microsoft Visual Studio 2008 的Microsoft Synchronization Services for ADO.NET,可以通过双层、N 层和基于服务的体系结构同步来自不同来源的数据。
 
Synchronization Services API 提供了一组用于在数据服务和本地存储区之间同步数据的组件,而不是仅仅用于复制数据库及其架构。应用程序正越来越多地用于移动客户端,如便携式计算机和设备。由于这些移动客户端与中央服务器没有连贯或可靠的网络连接,因此对于这些应用程序而言,能够在客户端上使用数据的一份本地副本十分重要。同等重要的一点是:在网络连接可用时,需要能够将数据的本地副本与中央服务器同步。Synchronization Services API 以 ADO.NET 数据访问 API 为蓝本,提供了一种直观的数据同步手段。Synchronization Services 对构建依靠连续网络连接的应用程序这一工作进行了合乎逻辑的扩展,使我们得以针对断续连接的网络环境开发应用程序。
 
相关代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

using Microsoft.Synchronization;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization.Data.SqlServerCe;
using Microsoft.Synchronization.Data.Server;
using System.Data.SqlServerCe;


namespace SynchrnoizationDemo
{
    public partial class frmMain : Form
    {
        #region 定义常规数据区
        private const string strServerListTableName = "ServerList";
        private const string strUserListTableName = "UserList";

        private const string strCreationTrackingColumn = @"create_timestamp";
        private const string strUpdateTrackingColumn = @"update_timestamp";
        private const string strDeletionTrackingColumn = @"update_timestamp";
        private const string strUpdateOriginatorIdColumn = @"update_originator_id";

        private const string strNoClientDBWarnString = "客户端数据库不存在,请首先执行 双向同步 命令";
        #endregion

        #region 定义变量区
        private string strServerIP = @"(local)";
        private string strServerDataBaseName = "SyncDemo";
        private string strLoginUser = "sa";
        private string strLoginPassWord = "sa";
        private string strServerConnectString = "";

        private string strClientDataBasename = Application.StartupPath + @"\ClientDB.sdf";
        private string strClientConnectString = "";

        private bool blnOperationClient = true;
        private string strOperationTable = strServerListTableName;
        #endregion

        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            //  初始化相关参数
            SetEnvironmentValue();
        }

        #region 通用方法
        /// <summary>
        /// 获取相关参数
        /// </summary>
        private void GetEnvironmentValue()
        {
            strServerIP = txtServerIP.Text.Trim();
            strServerDataBaseName = txtServerDataBaseName.Text.Trim();
            strLoginUser = txtLoginUser.Text.Trim();
            strLoginPassWord = txtLoginPassWord.Text.Trim();
            strServerConnectString = "Data Source="+strServerIP+";Initial Catalog="+strServerDataBaseName+";User ID="+strLoginUser+";Password="+strLoginPassWord+";";

            strClientDataBasename = txtClientDataBaseFileName.Text.Trim();
            strClientConnectString = "Data Source=" + strClientDataBasename;

            blnOperationClient = rbClient.Checked;
            strOperationTable = tabMain.SelectedIndex == 0 ? strServerListTableName : strUserListTableName;
        }
        /// <summary>
        /// 显示相关参数
        /// </summary>
        private void SetEnvironmentValue()
        {
            txtServerIP.Text = strServerIP;
            txtServerDataBaseName.Text = strServerDataBaseName;
            txtLoginUser.Text = strLoginUser;
            txtLoginPassWord.Text = strLoginPassWord;
            txtClientDataBaseFileName.Text = strClientDataBasename;
            
            if (blnOperationClient)
            {
                rbClient.Checked=true;
                rbServer.Checked=false;
            }
            else
            {
                rbServer.Checked=true;
                rbClient.Checked=false;
            }
        }
        /// <summary>
        /// 检查客户端数据库是否存在
        /// </summary>
        /// <returns></returns>
        private Boolean CheckClientDb()
        {
            //这里默认已经调用了GetEnvironmentValue函数
            return File.Exists(strClientDataBasename);
        }
        #endregion

        #region 刷新数据
        /// <summary>
        /// 刷新调用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btRefersh_Click(object sender, EventArgs e)
        {
            btRefersh.Enabled = false;
            //RefreshData(tabMain.SelectedTab.Text.Replace("表", ""));
            RefreshData(strServerListTableName);
            RefreshData(strUserListTableName);
            btRefersh.Enabled = true;
        }

        /// <summary>
        /// 数据刷新
        /// </summary>
        /// <param name="sTableName"></param>
        private void RefreshData(string sTableName)
        {
            GetEnvironmentValue();

            string sSql = "Select * from " + sTableName;
            
            DataTable dtQuery;

            try
            {
                #region 读取服务器端
                SqlDataAdapter serverLoadAdapter = new SqlDataAdapter(sSql, strServerConnectString);
                dtQuery = new DataTable();
                serverLoadAdapter.Fill(dtQuery);
                RemoveServerTrackingColumns(dtQuery);
                switch (sTableName)
                {
                    case strServerListTableName:
                        dgSLServer.DataSource = dtQuery;
                        break;
                    case strUserListTableName:
                        dgULServer.DataSource = dtQuery;
                        break;
                }
                #endregion

                #region 读取客户端
                if (CheckClientDb())
                {
                    SqlCeDataAdapter clientLoadAdapter = new SqlCeDataAdapter(sSql,strClientConnectString);
                    dtQuery = new DataTable();
                    clientLoadAdapter.Fill(dtQuery);
                    RemoveClientTrackingColumns(dtQuery);
                    switch (sTableName)
                    {
                        case strServerListTableName:
                            dgSLClient.DataSource = dtQuery;
                            break;
                        case strUserListTableName:
                            dgULClient.DataSource = dtQuery;
                            break;
                    }
                }
                else
                {
                    MessageBox.Show(strNoClientDBWarnString);
                }
                #endregion
            }
            catch (System.Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        /// <summary>
        /// 去除客户端表中不需要显示的列
        /// </summary>
        /// <param name="dataTable"></param>
        private static void RemoveClientTrackingColumns(DataTable dataTable)
        {
            if (dataTable.Columns.Contains("__sysInsertTxBsn"))
            {
                dataTable.Columns.Remove("__sysInsertTxBsn");
            }

            if (dataTable.Columns.Contains("__sysChangeTxBsn"))
            {
                dataTable.Columns.Remove("__sysChangeTxBsn");
            }
        }
        /// <summary>
        /// 去除服务器端表中不需要显示的列
        /// </summary>
        /// <param name="dataTable"></param>
        private static void RemoveServerTrackingColumns(DataTable dataTable)
        {
            if (dataTable.Columns.Contains("update_timestamp"))
            {
                dataTable.Columns.Remove("update_timestamp");
            }

            if (dataTable.Columns.Contains("create_timestamp"))
            {
                dataTable.Columns.Remove("create_timestamp");
            }

            if (dataTable.Columns.Contains("update_originator_id"))
            {
                dataTable.Columns.Remove("update_originator_id");
            }

        }
        #endregion

        #region 同步数据
        /// <summary>
        /// 同步数据调用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btSync_Click(object sender, EventArgs e)
        {
            btSync.Enabled = false;
            panOperation.Enabled = false;
            SynchronizeData();
            btRefersh_Click(null, null);
            panOperation.Enabled = true;
            btSync.Enabled = true;
        }
        /// <summary>
        /// 数据同步
        /// </summary>
        private void SynchronizeData()
        {
            #region 初始化
            GetEnvironmentValue();

            SyncAgent syncAgent = new SyncAgent();
            #endregion
            try
            {

                #region 服务器端准备
                DbServerSyncProvider serverSyncProvider = new DbServerSyncProvider();
                SqlConnection serverConnection = new SqlConnection(strServerConnectString);
                serverSyncProvider.Connection = serverConnection;
                syncAgent.RemoteProvider = serverSyncProvider;
                #endregion


                #region 客户端准备
                if (!CheckClientDb())
                {
                    SqlCeEngine clientEngine = new SqlCeEngine(strClientConnectString);
                    clientEngine.CreateDatabase();
                    clientEngine.Dispose();
                }
                SqlCeClientSyncProvider clientSyncProvider = new SqlCeClientSyncProvider(strClientConnectString);
                syncAgent.LocalProvider = clientSyncProvider;
                #endregion


                #region SyncTable和SyncGroup准备
                //  ServerList表
                SyncTable tableServerList = new SyncTable(strServerListTableName);
                tableServerList.CreationOption = TableCreationOption.DropExistingOrCreateNewTable;
                tableServerList.SyncDirection = SyncDirection.Bidirectional;

                //  UserList表
                SyncTable tableUserList = new SyncTable(strUserListTableName);
                tableUserList.CreationOption = TableCreationOption.DropExistingOrCreateNewTable;
                tableUserList.SyncDirection = SyncDirection.Bidirectional;

                //  SyncGroup
                SyncGroup syncGroup = new SyncGroup("SyncDemo");
                tableServerList.SyncGroup = syncGroup;
                tableUserList.SyncGroup = syncGroup;

                syncAgent.Configuration.SyncTables.Add(tableServerList);
                syncAgent.Configuration.SyncTables.Add(tableUserList);
                #endregion

                #region SyncAdapter准备

                #region ServerList准备
                SqlSyncAdapterBuilder ServerListBuilder = new SqlSyncAdapterBuilder();
                ServerListBuilder.Connection = serverConnection;
                ServerListBuilder.SyncDirection = SyncDirection.Bidirectional;

                // 主表及其相关列
                ServerListBuilder.TableName = strServerListTableName;
                ServerListBuilder.DataColumns.Add("ServerID");
                ServerListBuilder.DataColumns.Add("ServerIP");
                ServerListBuilder.DataColumns.Add("ServerBuyTime");

                // tombstone表及其相关列
                ServerListBuilder.TombstoneTableName = strServerListTableName + "_tombstone";
                ServerListBuilder.TombstoneDataColumns.Add("ServerID");
                ServerListBuilder.TombstoneDataColumns.Add("ServerIP");
                ServerListBuilder.TombstoneDataColumns.Add("ServerBuyTime");

                // 相关的跟踪列
                ServerListBuilder.CreationTrackingColumn = strCreationTrackingColumn;
                ServerListBuilder.UpdateTrackingColumn = strUpdateTrackingColumn;
                ServerListBuilder.DeletionTrackingColumn = strDeletionTrackingColumn;
                ServerListBuilder.UpdateOriginatorIdColumn = strUpdateOriginatorIdColumn;

                SyncAdapter ServerListSyncAdapter = ServerListBuilder.ToSyncAdapter();
                ((SqlParameter)ServerListSyncAdapter.SelectIncrementalInsertsCommand.Parameters["@sync_last_received_anchor"]).DbType = DbType.Binary;
                ((SqlParameter)ServerListSyncAdapter.SelectIncrementalInsertsCommand.Parameters["@sync_new_received_anchor"]).DbType = DbType.Binary;
                serverSyncProvider.SyncAdapters.Add(ServerListSyncAdapter);
                #endregion

                #region UserList准备
                SqlSyncAdapterBuilder UserListBuilder = new SqlSyncAdapterBuilder();
                UserListBuilder.SyncDirection = SyncDirection.Bidirectional;
                UserListBuilder.Connection = serverConnection;

                // 主表及其相关列
                UserListBuilder.TableName = strUserListTableName;
                UserListBuilder.DataColumns.Add("UserID");
                UserListBuilder.DataColumns.Add("UserName");
                UserListBuilder.DataColumns.Add("UserPW");
 
                // tombstone表及其相关列
                UserListBuilder.TombstoneTableName = strUserListTableName + "_tombstone";
                UserListBuilder.TombstoneDataColumns.Add("UserID");
                UserListBuilder.TombstoneDataColumns.Add("UserName");
                UserListBuilder.TombstoneDataColumns.Add("UserPW");
 
                // 相关的跟踪列
                UserListBuilder.CreationTrackingColumn = strCreationTrackingColumn;
                UserListBuilder.UpdateTrackingColumn = strUpdateTrackingColumn;
                UserListBuilder.DeletionTrackingColumn = strDeletionTrackingColumn;
                UserListBuilder.UpdateOriginatorIdColumn = strUpdateOriginatorIdColumn;


                SyncAdapter UserListSyncAdapter = UserListBuilder.ToSyncAdapter();
                ((SqlParameter)UserListSyncAdapter.SelectIncrementalInsertsCommand.Parameters["@sync_last_received_anchor"]).DbType = DbType.Binary;
                ((SqlParameter)UserListSyncAdapter.SelectIncrementalInsertsCommand.Parameters["@sync_new_received_anchor"]).DbType = DbType.Binary;
                serverSyncProvider.SyncAdapters.Add(UserListSyncAdapter);
                #endregion

                #endregion

                #region 数据同步
                SqlCommand anchorCmd = new SqlCommand();
                anchorCmd.CommandType = CommandType.Text;
                anchorCmd.CommandText = "Select @" + SyncSession.SyncNewReceivedAnchor + "= @@DBTS";// " = @@DBTS";
                anchorCmd.Parameters.Add("@" + SyncSession.SyncNewReceivedAnchor, SqlDbType.Timestamp).Direction = ParameterDirection.Output;
                serverSyncProvider.SelectNewAnchorCommand = anchorCmd;

                SqlCommand clientIdCmd = new SqlCommand();
                clientIdCmd.CommandType = CommandType.Text;
                clientIdCmd.CommandText = "SELECT @" + SyncSession.SyncOriginatorId + " = 1";
                clientIdCmd.Parameters.Add("@" + SyncSession.SyncOriginatorId, SqlDbType.Int).Direction = ParameterDirection.Output;

                serverSyncProvider.SelectClientIdCommand = clientIdCmd;

                syncAgent.Synchronize();
                #endregion   

            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
        #endregion

        #region 增量操作
        #region 产生各种随机数据
        /// <summary>
        /// 产生随机IP
        /// </summary>
        /// <returns></returns>
        private string ReturnRandomIP(Random rand)
        {
            string sRe = "192.168." + rand.Next(0, 256).ToString() + "." + rand.Next(0, 256).ToString();
            return sRe;
        }
        /// <summary>
        /// 产生随机ID
        /// </summary>
        /// <param name="rand"></param>
        /// <returns></returns>
        private string ReturnRandomID(Random rand)
        {
            return rand.Next((int)(DateTime.Now.ToFileTime() % 10000)).ToString();
        }

        /// <summary>
        /// 产生随机字符
        /// </summary>
        /// <param name="rand"></param>
        /// <returns></returns>
        private char ReturnRandomChar(Random rand)
        {
            int ret = rand.Next(122);
            while (ret < 48 || (ret > 57 && ret < 65) || (ret > 90 && ret < 97))
            {
                ret = rand.Next(122);
            }
            return (char)ret;
        }
        /// <summary>
        /// 产生随机字符串
        /// </summary>
        /// <param name="rand"></param>
        /// <returns></returns>
        private string ReturnRandomString(Random rand)
        {
            int length = 10;
            StringBuilder sb = new StringBuilder(length);
            for (int i = 0; i < length; i++)
            {
                sb.Append(ReturnRandomChar(rand));
            }
            return sb.ToString();
        }
        #endregion

        /// <summary>
        /// 返回一个随机操作的ID
        /// </summary>
        private string ReturnRandomUpdateOrDeleteID(Random rand)
        {
            DataTable dtRef = new DataTable();
            if (strOperationTable == strServerListTableName)
            {
                if (blnOperationClient)
                {
                    dtRef = (DataTable)dgSLClient.DataSource;
                }
                else
                {
                    dtRef = (DataTable)dgSLServer.DataSource;
                }
            }
            else
            {
                if (blnOperationClient)
                {
                    dtRef = (DataTable)dgULClient.DataSource;
                }
                else
                {
                    dtRef = (DataTable)dgULServer.DataSource;
                }
            }
            int iTotalRows = dtRef.Rows.Count;
            return dtRef.Rows[rand.Next(0, iTotalRows)][0].ToString();
        }
        /// <summary>
        /// 具体执行增删改的操作
        /// </summary>
        /// <param name="CommandString"></param>
        private void ExecuteOperation(string CommandString)
        {
            if (blnOperationClient)
            {
                #region 客户端操作
                if (CheckClientDb())
                {
                    SqlCeConnection conn = new SqlCeConnection(strClientConnectString);
                    SqlCeCommand cmd = new SqlCeCommand();
                    cmd.Connection = conn;
                    cmd.CommandText = CommandString.ToString();
                    try
                    {
                        conn.Open();
                        cmd.ExecuteNonQuery();
                    }
                    catch (System.Exception exp)
                    {
                        MessageBox.Show(exp.Message);
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
                else
                {
                    MessageBox.Show(strNoClientDBWarnString);
                }
                #endregion
            }
            else
            {
                #region 服务器端操作
                SqlConnection conn = new SqlConnection(strServerConnectString);
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = conn;
                cmd.CommandText = CommandString;
                try
                {
                    conn.Open();
                    cmd.ExecuteNonQuery();
                }
                catch (System.Exception exp)
                {
                    MessageBox.Show(exp.Message);
                }
                finally
                {
                    conn.Close();
                }
                #endregion
            }

            RefreshData(strOperationTable);
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btUpdate_Click(object sender, EventArgs e)
        {
            btUpdate.Enabled = false;

            #region 初始化
            GetEnvironmentValue();
            Random rand = new Random();
            StringBuilder sSql = new StringBuilder();
            if (strOperationTable == strServerListTableName)
            {
                //update ServerList set ServerIP='123.12',ServerBuyTime=GetDate() where ServerID=1
                sSql.Append(@" update ServerList ");
                sSql.Append(@" set ServerIP='"+ReturnRandomIP(rand)+"', ");       //ServerIP
                sSql.Append(@" ServerBuyTime=GetDate() ");      //ServerBuyTime
                sSql.Append(@" where ServerID="+ReturnRandomUpdateOrDeleteID(rand)+" ");    //UpdateID
            }
            else
            {
                sSql.Append(@" update UserList ");
                sSql.Append(@" set UserName = '"+ReturnRandomString(rand)+"', ");         //UserName
                sSql.Append(@" UserPW = '"+ReturnRandomString(rand)+"' ");                //UserPW
                sSql.Append(@" where UserID="+ReturnRandomUpdateOrDeleteID(rand)+" ");    //UpdateID
            }
            #endregion

            ExecuteOperation(sSql.ToString()); 

            btUpdate.Enabled = true;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btAdd_Click(object sender, EventArgs e)
        {
            btAdd.Enabled = false;

            #region 初始化
            GetEnvironmentValue();
            Random rand = new Random();
            StringBuilder sSql = new StringBuilder();
            if (strOperationTable == strServerListTableName)
            {
                sSql.Append(@" insert into ServerList (ServerID, ServerIP, ServerBuyTime) ");
                sSql.Append(@" values( ");
                sSql.Append(@" " + ReturnRandomID(rand) + ", ");   //ServerID
                sSql.Append(@" '" + ReturnRandomIP(rand) + "', "); //ServerIP
                sSql.Append(@" GetDate() ");    //ServerBuyTime
                sSql.Append(@" ) ");
            }
            else
            {
                sSql.Append(@" insert into UserList (UserID, UserName, UserPW) ");
                sSql.Append(@" values( ");
                sSql.Append(@" " + ReturnRandomID(rand) + ", ");       //UserID
                sSql.Append(@" '" + ReturnRandomString(rand) + "', ");    //UserName
                sSql.Append(@" '" + ReturnRandomString(rand) + "' ");     //UserPW
                sSql.Append(@" ) ");
            }
            #endregion

            ExecuteOperation(sSql.ToString());

            btAdd.Enabled = true;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btDelete_Click(object sender, EventArgs e)
        {
            btDelete.Enabled = false;

            #region 初始化
            GetEnvironmentValue();
            Random rand = new Random();
            StringBuilder sSql = new StringBuilder();
            if (strOperationTable == strServerListTableName)
            {
                sSql.Append(@"delete from ServerList where ServerID="+ReturnRandomUpdateOrDeleteID(rand));
            }
            else
            {
                sSql.Append(@"delete from UserList where UserID="+ReturnRandomUpdateOrDeleteID(rand));
            }
            #endregion

            ExecuteOperation(sSql.ToString());

            btDelete.Enabled = true;
        }
        #endregion

    }
}
 

Demo与源码下载: 

 

本文转自 高阳 51CTO博客,原文链接:http://blog.51cto.com/xiaoyinnet/196086 ,如需转载请自行联系原作者

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
相关文章
|
8天前
|
运维 Cloud Native 持续交付
深入理解云原生架构及其在现代企业中的应用
随着数字化转型的浪潮席卷全球,企业正面临着前所未有的挑战与机遇。云计算技术的迅猛发展,特别是云原生架构的兴起,正在重塑企业的IT基础设施和软件开发模式。本文将深入探讨云原生的核心概念、关键技术以及如何在企业中实施云原生策略,以实现更高效的资源利用和更快的市场响应速度。通过分析云原生架构的优势和面临的挑战,我们将揭示它如何助力企业在激烈的市场竞争中保持领先地位。
|
6天前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。
|
17天前
|
监控 前端开发 数据可视化
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
@icraft/player-react 是 iCraft Editor 推出的 React 组件库,旨在简化3D数字孪生场景的前端集成。它支持零配置快速接入、自定义插件、丰富的事件和方法、动画控制及实时数据接入,帮助开发者轻松实现3D场景与React项目的无缝融合。
64 8
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
|
6天前
|
运维 Cloud Native 持续交付
云原生技术深度探索:重塑现代IT架构的无形之力####
本文深入剖析了云原生技术的核心概念、关键技术组件及其对现代IT架构变革的深远影响。通过实例解析,揭示云原生如何促进企业实现敏捷开发、弹性伸缩与成本优化,为数字化转型提供强有力的技术支撑。不同于传统综述,本摘要直接聚焦于云原生技术的价值本质,旨在为读者构建一个宏观且具体的技术蓝图。 ####
|
17天前
|
人工智能 运维 算法
引领企业未来数字基础架构浪潮,中国铁塔探索超大规模分布式算力
引领企业未来数字基础架构浪潮,中国铁塔探索超大规模分布式算力
|
13天前
|
运维 Kubernetes Docker
深入理解容器化技术及其在微服务架构中的应用
深入理解容器化技术及其在微服务架构中的应用
29 1
|
19天前
|
监控 Java 微服务
从零构建微服务架构:一次深度技术探索之旅####
本文作为一篇深度技术分享,引领读者踏上自底向上搭建微服务架构的征途,旨在通过实战经验剖析,揭示微服务转型背后的技术挑战与解决方案。不同于常规摘要仅概述内容,本文摘要将直接以故事化手法,简述作者从单体应用困境出发,逐步迈向微服务化的心路历程,涵盖关键决策点、技术选型考量及实践收获,激发读者对微服务架构设计与实现的浓厚兴趣。 ####
|
20天前
|
Cloud Native 持续交付 云计算
深入理解云原生技术及其在现代IT架构中的应用
在数字化浪潮的推动下,云原生技术已成为企业转型的关键。本文将通过浅显易懂的语言和生动的比喻,带领读者探索云原生的核心概念、优势以及如何在企业中实现云原生架构。我们将一起揭开云原生的神秘面纱,了解它如何助力企业快速适应市场变化,提升业务的灵活性和创新能力。
|
13天前
|
Cloud Native 持续交付 云计算
云原生技术在现代IT架构中的转型力量####
本文深入剖析了云原生技术的精髓,探讨其在现代IT架构转型中的关键作用与实践路径。通过具体案例分析,展示了云原生如何赋能企业实现更高效的资源利用、更快的迭代速度以及更强的系统稳定性,为读者提供了一套可借鉴的实施框架与策略。 ####
19 0
|
14天前
|
Cloud Native 持续交付 云计算
云原生架构:重塑企业IT的未来####
本文深入探讨了云原生架构的兴起背景、核心理念、技术优势以及在现代企业IT系统中的应用实践。云原生架构以其高度的灵活性、可扩展性和敏捷性,正逐步成为企业数字化转型的关键驱动力。通过容器化、微服务、持续集成/持续部署(CI/CD)等关键技术,云原生架构能够加速软件开发周期,提升系统稳定性和运维效率,为企业带来前所未有的商业价值。 ####
22 0