首頁 資料庫 mysql教程 SqlServer调用外部程序实现数据同步

SqlServer调用外部程序实现数据同步

Jun 07, 2016 pm 03:21 PM
sqlserver 同步 外部 實現 數據 程式 呼叫 首先

首先创建两个数据库:SyncA是数据源,SyncB是对SyncA进行同步的数据库。 在SyncA和SyncB中分别创建Source表和Target表,实际业务中,两张表的结构大多不相同。 然后创建一个类库的项目:MySync(注意项目的版本,Sql08不支持的.net 4.0及更高版本) 下面是同

首先创建两个数据库:SyncA是数据源,SyncB是对SyncA进行同步的数据库。

SqlServer调用外部程序实现数据同步

在SyncA和SyncB中分别创建Source表和Target表,实际业务中,两张表的结构大多不相同。

SqlServer调用外部程序实现数据同步   SqlServer调用外部程序实现数据同步

然后创建一个类库的项目:MySync(注意项目的版本,Sql08不支持的.net 4.0及更高版本)

SqlServer调用外部程序实现数据同步

下面是同步程序代码:

<span>using</span><span> System;
</span><span>using</span><span> System.Data;
</span><span>using</span><span> System.Data.Sql;
</span><span>using</span><span> Microsoft.SqlServer.Server;
</span><span>using</span><span> System.Data.SqlClient;
</span><span>using</span><span> System.Data.SqlTypes;

</span><span>namespace</span><span> MySync
{
    </span><span>public</span> <span>class</span><span> SyncDataBase
    {<br>       [SqlFunction(SystemDataAccess = SystemDataAccessKind.Read, DataAccess = DataAccessKind.Read)]
        </span><span>public</span> <span>static</span> <span>string</span> Sync(<span>string</span><span> strSql)
        {
            </span><span>string</span> result = <span>"</span><span>true</span><span>"</span><span>;

            </span><span>string</span> strConn = <span>@"</span><span>Data Source=localhost;Initial Catalog=SyncB;User ID=sa;Password=123@abc;</span><span>"</span><span>;
            </span><span>try</span><span>
            {
                </span><span>using</span> (SqlConnection connection = <span>new</span><span> SqlConnection(strConn))
                {
                    connection.Open();
                    SqlCommand command </span>= <span>new</span><span> SqlCommand(strSql, connection);
                    command.CommandType </span>=<span> CommandType.Text;
                    command.ExecuteNonQuery();
                    connection.Close();
                }
            }
            </span><span>catch</span><span> (Exception ex)
            {
                result </span>= <span>"</span><span>false:</span><span>"</span> +<span> ex.ToString();
            }

            </span><span>return</span><span> result;
        }
    }
}</span>
登入後複製

接下来要对类库项目进行签名,签名后编译【项目】:

SqlServer调用外部程序实现数据同步

SqlServer调用外部程序实现数据同步

启用CLR功能:默认情况下,Sql Server中的CLR是关闭的,所以我们要执行如下命令打开SyncA数据库的CLR。

<span>exec</span> sp_configure <span>'</span><span>clr enabled</span><span>'</span>,<span>1</span>  
<span>reconfigure</span>  
<span>go</span>
登入後複製

SqlServer调用外部程序实现数据同步

注册DLL:

为了调用我们写的那个方法,需要在SQL Server中注册我们刚刚编译好的那个DLL。在此之前,要知道在这个项目中如果要访问服务器之外的资源是要配置权限的。如果不配置,后面操作中会出现类似下面的错误。我找到的关于授权配置的内容:连接。

SqlServer调用外部程序实现数据同步

创建登录名和密钥,如果程序集有变更,要删除密钥和登录名重新创建:

<span>USE</span><span> master; 
</span><span>GO</span>  
 
<span>CREATE</span> ASYMMETRIC <span>KEY</span> SQLCLRSyncKey <span>FROM</span> EXECUTABLE <span>FILE</span> <span>=</span> <span>'</span><span>C:\MySync.dll</span><span>'</span>  
<span>CREATE</span> LOGIN SQLCLRSyncLogin <span>FROM</span> ASYMMETRIC <span>KEY</span><span> SQLCLRSyncKey   
</span><span>GRANT</span> EXTERNAL ACCESS ASSEMBLY <span>TO</span><span> SQLCLRSyncLogin; 
</span><span>GO</span> 
登入後複製

<span>DROP</span><span> LOGIN SQLCLRSyncLogin
</span><span>DROP</span> ASYMMETRIC <span>KEY</span> SQLCLRSyncKey
登入後複製

创建程序集,DLL变更后要删除重新创建:

<span>USE</span><span> SyncA; 
</span><span>GO</span>  

<span>create</span><span> ASSEMBLY MySync 
</span><span>FROM</span> <span>'</span><span>C:\MySync.dll</span><span>'</span>
<span>WITH</span> PERMISSION_SET <span>=</span><span> EXTERNAL_ACCESS;
</span><span>GO</span> 
登入後複製

然后创建一个函数用于调用这个DLL:

<span>CREATE</span> <span>FUNCTION</span><span> dbo.fun_sync
(  
    </span><span>@strSql</span> <span>nvarchar</span>(<span>max</span><span>)
)
</span><span>RETURNS</span> <span>nvarchar</span>(<span>max</span><span>)  
</span><span>AS</span> EXTERNAL NAME <span>[</span><span>MySync</span><span>]</span>.<span>[</span><span>MySync.SyncDataBase</span><span>]</span>.<span>[</span><span>Sync</span><span>]</span> 
登入後複製

先来测试一下,在SyncA中执行查询:

<span>SELECT</span> dbo.fun_sync(<span>'</span><span>insert into Target(Id,Name,SyncTime) values (null,null,getdate())</span><span>'</span>)
登入後複製

SqlServer调用外部程序实现数据同步

SyncB中添加了一条数据:

SqlServer调用外部程序实现数据同步

下面使用触发器自动的从SyncA中将数据同步到SyncB中,其中的tt表是我临时创建的,用于保存触发器调用返回的结果:

<span>create</span> <span>Trigger</span><span> tr_source
</span><span>on</span> <span>[</span><span>Source</span><span>]</span>
<span>for</span> <span>INSERT</span>

<span>AS</span>
<span>begin</span>
<span>declare</span> <span>@strSql</span> <span>nvarchar</span>(<span>max</span><span>)
</span><span>select</span> <span>@strSql</span><span>=</span><span>'</span><span>insert into Target(Id,Name,SyncTime) values (</span><span>'''</span><span>+</span><span>cast</span>(Id <span>as</span> <span>nvarchar</span>)<span>+</span><span>'''</span><span>,</span><span>'''</span><span>+</span>Title<span>+</span><span>'''</span><span>,getdate())</span><span>'</span> <span>from</span><span> inserted

</span><span>--</span><span>执行</span>
<span>declare</span> <span>@result</span> <span>nvarchar</span>(<span>max</span><span>)
</span><span>select</span> <span>@result</span><span>=</span>dbo.fun_sync(<span>@strSql</span><span>)

</span><span>insert</span> <span>into</span> tt(tt) <span>values</span> (<span>@result</span><span>)
</span><span>end</span>
登入後複製

直接执行函数没有问题,但是触发器去调用函数执行却出现异常:

<span>false:System.Data.SqlClient.SqlException: 其他会话正在使用事务的上下文。     
在 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)     
在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)     
在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)     
在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)     
在 System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)     
在 System.Data.SqlClient.SqlInternalConnectionTds.PropagateTransactionCookie(Byte[] cookie)     
在 System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)     
在 System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)     
在 System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)    
在 System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)     
在 System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)     
在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)     
在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)     
在 System.Data.SqlClient.SqlConnection.Open()     
在 MySync.SyncDataBase.Sync(String strSql)</span>
登入後複製

这个错误中包含了一个false值,说明触发器调用时已经可以走到DLL这一步了。考虑到在查询中直接执行函数,走到DLL这一步是没有错误的。那么错误就发生在触发器和DLL调用产生的冲突,冲突在访问数据库上面,再深入的原因,我也没有找到。

下面使用另外一种方式实现同步,因为错误是触发器和DLL的数据库访问冲突,那么我就绕过数据库的访问。将触发器产生的SQL脚本保存到某个目录下面,然后通过其他程序监听这个目录,执行脚本文件,实现同步。

类库代码

<span>using</span><span> System;
</span><span>using</span><span> System.Data;
</span><span>using</span><span> System.Data.Sql;
</span><span>using</span><span> Microsoft.SqlServer.Server;
</span><span>using</span><span> System.Data.SqlClient;
</span><span>using</span><span> System.Data.SqlTypes;
</span><span>using</span><span> System.IO;

</span><span>namespace</span><span> MySync
{
    </span><span>public</span> <span>class</span><span> SyncDataBase
    {
        [SqlFunction(SystemDataAccess </span>= SystemDataAccessKind.Read, DataAccess =<span> DataAccessKind.Read)]
        </span><span>public</span> <span>static</span> <span>string</span> Sync(<span>string</span><span> strSql)
        {
            </span><span>string</span> result = <span>"</span><span>true</span><span>"</span><span>;

            </span><span>try</span><span>
            {
                </span><span>if</span> (!Directory.Exists(<span>"</span><span>c:\\SyncLog</span><span>"</span><span>))
                {
                    Directory.CreateDirectory(</span><span>"</span><span>c:\\SyncLog</span><span>"</span><span>);
                }
                </span><span>string</span> fileName = <span>@"</span><span>c:\\SyncLog\\</span><span>"</span> + DateTime.Now.ToString(<span>"</span><span>yyyyMMddHHmmss</span><span>"</span>) + <span>"</span><span>.txt</span><span>"</span><span>;
                </span><span>if</span> (<span>File.Exists(fileName))
                    File.Delete(fileName);

                </span><span>using</span> (StreamWriter sw =<span> File.CreateText(fileName))
                {
                    sw.WriteLine(strSql);
                }
            }
            </span><span>catch</span><span> (Exception ex)
            {
                result </span>= <span>"</span><span>false:</span><span>"</span> +<span> ex.ToString();
            }

            </span><span>return</span><span> result;
        }
    }
}</span>
登入後複製

另外创建一个监听程序:MyListen

<span>using</span><span> System;
</span><span>using</span><span> System.Data;
</span><span>using</span><span> System.Data.Sql;
</span><span>using</span><span> System.Data.SqlClient;
</span><span>using</span><span> System.Data.SqlTypes;
</span><span>using</span><span> System.Configuration;
</span><span>using</span><span> System.Threading;
</span><span>using</span><span> System.IO;

</span><span>namespace</span><span> MyListen
{
    </span><span>class</span><span> Program
    {
        </span><span>static</span> <span>void</span> Main(<span>string</span><span>[] args)
        {
            </span><span>string</span> connSync = ConfigurationManager.ConnectionStrings[<span>"</span><span>connSync</span><span>"</span><span>].ToString();
            </span><span>string</span> filePath = ConfigurationManager.AppSettings[<span>"</span><span>filePath</span><span>"</span><span>];
            </span><span>while</span> (<span>true</span><span>)
            {
                </span><span>//</span><span>所有txt文件</span>
                <span>string</span>[] fileList = DirFile.GetFileNames(filePath, <span>"</span><span>*.txt</span><span>"</span>, <span>true</span><span>);
                </span><span>foreach</span> (<span>var</span> f <span>in</span><span> fileList)
                {
                    </span><span>string</span> strSql = <span>""</span><span>;
                    </span><span>using</span> (StreamReader sr = <span>new</span><span> StreamReader(f))
                    {
                        </span><span>string</span><span> line;
                        </span><span>while</span> ((line = sr.ReadLine()) != <span>null</span><span>)
                        {
                            strSql </span>+= line + <span>"</span> <span>"</span><span>;
                        }
                        sr.Close();
                    }
                    </span><span>try</span><span>
                    {
                        </span><span>using</span> (SqlConnection connection = <span>new</span><span> SqlConnection(connSync))
                        {
                            connection.Open();
                            SqlCommand command </span>= <span>new</span><span> SqlCommand(strSql, connection);
                            command.CommandType </span>=<span> CommandType.Text;
                            command.ExecuteNonQuery();
                            connection.Close();
                        }
                    }
                    </span><span>catch</span><span> (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                    File.Delete(f);
                }
                </span><span>//</span><span>每10秒扫描一次</span>
                Thread.Sleep(<span>5</span> * <span>1000</span><span>);
            }
        }
    }
}</span>
登入後複製

只要将监听程序打开,就可以实现对数据的同步。项目和数据库下载。

参考:

http://msdn.microsoft.com/zh-cn/library/Microsoft.SqlServer.Server.SqlFunctionAttribute_properties(v=vs.100).aspx

http://blog.sina.com.cn/s/blog_59c41d0d0100esjn.html

http://www.cnblogs.com/wshcn/archive/2011/12/02/2271630.html

http://www.cnblogs.com/edong/archive/2010/03/10/1682172.html

http://www.cnblogs.com/hsrzyn/archive/2013/05/28/1976555.html

 

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1666
14
CakePHP 教程
1426
52
Laravel 教程
1328
25
PHP教程
1273
29
C# 教程
1253
24
如何在iPhone中使Google地圖成為預設地圖 如何在iPhone中使Google地圖成為預設地圖 Apr 17, 2024 pm 07:34 PM

iPhone上的預設地圖是Apple專有的地理位置供應商「地圖」。儘管地圖越來越好,但它在美國以外的地區運作不佳。與谷歌地圖相比,它沒有什麼可提供的。在本文中,我們討論了使用Google地圖成為iPhone上的預設地圖的可行性步驟。如何在iPhone中使Google地圖成為預設地圖將Google地圖設定為手機上的預設地圖應用程式比您想像的要容易。請依照以下步驟操作–先決條件步驟–您必須在手機上安裝Gmail。步驟1–開啟AppStore。步驟2–搜尋“Gmail”。步驟3–點選Gmail應用程式旁

sqlserver怎麼匯入mdf文件 sqlserver怎麼匯入mdf文件 Apr 08, 2024 am 11:41 AM

匯入步驟如下:將 MDF 檔案複製到 SQL Server 的資料目錄(通常為 C:\Program Files\Microsoft SQL Server\MSSQL\DATA)。在 SQL Server Management Studio(SSMS)中,開啟資料庫並選擇「附加」。點選“新增”按鈕,選擇 MDF 檔案。確認資料庫名稱,點選確定按鈕即可。

sqlserver資料庫中已存在名為的物件怎麼解決 sqlserver資料庫中已存在名為的物件怎麼解決 Apr 05, 2024 pm 09:42 PM

對於 SQL Server 資料庫中已存在同名對象,需要採取下列步驟:確認物件類型(表格、檢視、預存程序)。如果物件為空,可使用 IF NOT EXISTS 跳過建立。如果物件有數據,使用不同名稱或修改結構。使用 DROP 刪除現有物件(謹慎操作,建議備份)。檢查架構更改,確保沒有引用刪除或重新命名的物件。

iPhone中缺少時鐘應用程式:如何修復 iPhone中缺少時鐘應用程式:如何修復 May 03, 2024 pm 09:19 PM

您的手機中缺少時鐘應用程式嗎?日期和時間仍將顯示在iPhone的狀態列上。但是,如果沒有時鐘應用程序,您將無法使用世界時鐘、碼錶、鬧鐘等多項功能。因此,修復時鐘應用程式的缺失應該是您的待辦事項清單的首位。這些解決方案可以幫助您解決此問題。修復1–放置時鐘應用程式如果您錯誤地從主畫面中刪除了時鐘應用程序,您可以將時鐘應用程式放回原位。步驟1–解鎖iPhone並開始向左側滑動,直到到達「應用程式庫」頁面。步驟2–接下來,在搜尋框中搜尋「時鐘」。步驟3–當您在搜尋結果中看到下方的「時鐘」時,請按住它並

怎麼查看sqlserver連接埠號 怎麼查看sqlserver連接埠號 Apr 05, 2024 pm 09:57 PM

若要查看 SQL Server 連接埠號碼:開啟 SSMS,連線到伺服器。在物件資源管理器中找到伺服器名稱,右鍵單擊它,然後選擇“屬性”。在「連線」標籤中,查看「TCP 連接埠」欄位。

sqlserver誤刪資料庫怎麼恢復 sqlserver誤刪資料庫怎麼恢復 Apr 05, 2024 pm 10:39 PM

若誤刪 SQL Server 資料庫,可採取下列步驟還原:停止資料庫活動;備份日誌檔案;檢查資料庫日誌;復原選項:從備份還原;從交易日誌還原;使用 DBCC CHECKDB;使用第三方工具。請定期備份資料庫並啟用交易日誌以防止資料遺失。

sqlserver服務無法啟動怎麼辦 sqlserver服務無法啟動怎麼辦 Apr 05, 2024 pm 10:00 PM

當 SQL Server 服務無法啟動時,可採取下列步驟解決:檢查錯誤日誌以確定根本原因。確保服務帳戶具有啟動服務的權限。檢查依賴項服務是否正在執行。禁用防毒軟體。修復 SQL Server 安裝。如果修復不起作用,重新安裝 SQL Server。

iPhone上的蜂窩數據網路速度慢:修復 iPhone上的蜂窩數據網路速度慢:修復 May 03, 2024 pm 09:01 PM

在iPhone上面臨滯後,緩慢的行動數據連線?通常,手機上蜂窩互聯網的強度取決於幾個因素,例如區域、蜂窩網絡類型、漫遊類型等。您可以採取一些措施來獲得更快、更可靠的蜂窩網路連線。修復1–強制重啟iPhone有時,強制重啟設備只會重置許多內容,包括蜂窩網路連線。步驟1–只需按一次音量調高鍵並放開即可。接下來,按降低音量鍵並再次釋放它。步驟2–過程的下一部分是按住右側的按鈕。讓iPhone完成重啟。啟用蜂窩數據並檢查網路速度。再次檢查修復2–更改資料模式雖然5G提供了更好的網路速度,但在訊號較弱

See all articles