gpt4 book ai didi

c# - 微软同步框架 : Cannot enumerate changes at the RelationalSyncProvider for table 'Table Name'

转载 作者:太空宇宙 更新时间:2023-11-03 20:00:16 25 4
gpt4 key购买 nike

看看下面的代码

这是我的 _cSynchronization 类,其中包含同步功能,连接字符串中的 (500) 表示超时 = 500

public static class _cSynchronization
{
public static int transactionCount;
public static uint BatchSize = 10000;
public static uint MemorySize = 20000;

public static List<string> _MGetAllTableList()
{
List<string> list = new List<string>();
DataRowCollection _dr = _CObjectsofClasses._obj_CDatabase._MGetDataRows("Select TABLE_NAME From INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME <> N'AUTOBACKUPSET' AND TABLE_NAME <> N'BINDATA' AND TABLE_NAME <> N'_ATTENDANCESTATUS' AND TABLE_NAME NOT like '%_tracking%' AND TABLE_TYPE ='BASE TABLE' AND TABLE_NAME <> N'schema_info' AND TABLE_NAME <> N'scope_info' AND TABLE_NAME <> N'scope_config' AND TABLE_NAME <> '_CLIENTNAME' AND TABLE_NAME <> '_TABSETTING' AND TABLE_NAME <> '_EMPLOYEEPAYMENT1' AND TABLE_NAME <> '_LOCALCOMPANYINFO' ORDER BY TABLE_NAME");
int a = 0;
string x = "";
if (_dr.Count > 0)
{
_CPubVar._value_I = 0;
_CPubVar._MaxValue_I = _dr.Count + 2;
_CPubVar._IsTableProcess_bool = true;
foreach (DataRow _row in _dr)
{
_CPubVar._value_I++;
_CPubVar._ProcessText_S = "Preparing Tables " + _CPubVar._value_I + " of " + _CPubVar._MaxValue_I;
x = _CObjectsofClasses._obj_CConvert._MConvertToString(_row[0]);
// serverConn.Open();
list.Add(x);
}
}
return list;
}
public static void SetUp(string _pTableName)
{
// Connection to SQL Server database
SqlConnection serverConn = new SqlConnection(_CObjectsofClasses._obj_CConnectionString._MGetServerConnectionString(500));
// Connection to SQL client database
SqlConnection clientConn = new SqlConnection(_CObjectsofClasses._obj_CConnectionString._MGetConnectionString(500));


// Create a scope named "product" and add tables to it.
DbSyncScopeDescription productScope = new DbSyncScopeDescription(_pTableName + "_SCOP");

// Select the colums to be included in the Collection Object

// Define the Products table.
DbSyncTableDescription productDescription =
SqlSyncDescriptionBuilder.GetDescriptionForTable(_pTableName,serverConn);
// Add the Table to the scope object.
productScope.Tables.Add(productDescription);

// Create a provisioning object for "product" and apply it to the on-premise database if one does not exist.
SqlSyncScopeProvisioning serverProvision = new SqlSyncScopeProvisioning(serverConn, productScope);
serverProvision.ObjectSchema = ".dbo";

//
serverProvision.SetCreateProceduresForAdditionalScopeDefault(DbSyncCreationOption.Create);
serverProvision.SetCreateTableDefault(DbSyncCreationOption.Skip);
serverProvision.SetCreateProceduresDefault(DbSyncCreationOption.CreateOrUseExisting);
serverProvision.SetCreateTrackingTableDefault(DbSyncCreationOption.CreateOrUseExisting);
serverProvision.SetCreateTriggersDefault(DbSyncCreationOption.CreateOrUseExisting);

if (!serverProvision.ScopeExists(_pTableName + "_SCOP"))
serverProvision.Apply();

// Provision the SQL client database from the on-premise SQL Server database if one does not exist.
SqlSyncScopeProvisioning clientProvision = new SqlSyncScopeProvisioning(clientConn, productScope);


if (!clientProvision.ScopeExists(_pTableName + "_SCOP"))
clientProvision.Apply();

// Shut down database connections.

serverConn.Close();

serverConn.Dispose();

clientConn.Close();

clientConn.Dispose();
}
public static List<_CSyncDetails> Synchronize(string _pScopeName, SyncDirectionOrder _pDirection)
{
// Connection to SQL Server database
SqlConnection serverConn = new SqlConnection(_CObjectsofClasses._obj_CConnectionString._MGetServerConnectionString(500));

// Connection to SQL client database
SqlConnection clientConn = new SqlConnection(_CObjectsofClasses._obj_CConnectionString._MGetConnectionString(500));

List<_CSyncDetails> _Statics = new List<_CSyncDetails>();

// Perform Synchronization between SQL Server and the SQL client.
SyncOrchestrator syncOrchestrator = new SyncOrchestrator();

// Create provider for SQL Server
SqlSyncProvider serverProvider = new SqlSyncProvider(_pScopeName, serverConn);

// Set the command timeout and maximum transaction size for the SQL Azure provider.
SqlSyncProvider clientProvider = new SqlSyncProvider(_pScopeName, clientConn);


clientProvider.CommandTimeout = serverProvider.CommandTimeout = 500;
//Set memory allocation to the database providers
clientProvider.MemoryDataCacheSize = serverProvider.MemoryDataCacheSize = MemorySize;


//Set application transaction size on destination provider.
serverProvider.ApplicationTransactionSize = BatchSize;


//Count transactions
serverProvider.ChangesApplied += new EventHandler<DbChangesAppliedEventArgs>(RemoteProvider_ChangesApplied);


// Set Local provider of SyncOrchestrator to the server provider
syncOrchestrator.LocalProvider = serverProvider;

// Set Remote provider of SyncOrchestrator to the client provider
syncOrchestrator.RemoteProvider = clientProvider;

// Set the direction of SyncOrchestrator session to Upload and Download
syncOrchestrator.Direction = _pDirection;

// Create SyncOperations Statistics Object

SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();
_Statics.Add(new _CSyncDetails { UploadChangesTotal = syncStats.UploadChangesTotal, SyncStartTime = syncStats.SyncStartTime, DownloadChangesTotal = syncStats.DownloadChangesTotal, SyncEndTime = syncStats.SyncEndTime });

// Display the Statistics

// Shut down database connections.

serverConn.Close();

serverConn.Dispose();

clientConn.Close();

clientConn.Dispose();
return _Statics;

}
}

这里是我同步的函数

 private void _MSync()
{

_CPubVar._IsContinue = true;
_CPubVar._PausebtnCondition = 0;
// _cSynchronization._MClearSyncprovision();

_CPubVar._Stop_bool = false;

this.Text += " - Started at : " + DateTime.Now;
string a = "";
// Define the Products table.
List<string> _Tablelist = new List<string>();
Collection<string> _ColNames = new Collection<string>();
_list1.Add(new _CSyncDetails { SyncStartTime = DateTime.Now });

_Tablelist.AddRange(_cSynchronization._MGetAllTableList());

SyncDirectionOrder _order = SyncDirectionOrder.Download;
_CPubVar._MaxValue_I = (_Tablelist.Count * 2);
_CPubVar._value_I = 0;
foreach (string tbl in _Tablelist)
{
try
{
a = Regex.Replace(Environment.MachineName + Environment.UserName, @"[^0-9a-zA-Z]+", "").ToUpper() + "_" + tbl + "_SCOPE";
_CPubVar._value_I++;
_CPubVar._ProcessText_S = "Sync Tables " + _CPubVar._value_I + " of " + _CPubVar._MaxValue_I;
_cSynchronization.SetUp(tbl);

if (_CPubVar._IsServerRunning_bool)
{
_order = SyncDirectionOrder.DownloadAndUpload;
}
else
{
if (tbl == "_BANK" || tbl == "_BANKACCOUNT" || tbl == "_CLIENTNAME" || tbl == "_PACKAGE" || tbl == "_PACKAGEDET" || tbl == "_PAYMENTEXPENCES" || tbl == "_PROJECT" || tbl == "_PROJECTDET" || tbl == "_REQUIREMENT" || tbl == "_REQUIREMENTDET" || tbl == "_SERVER" || tbl == "_UNIT" || tbl == "_ITEM" || tbl == "ManageUser" || tbl == "USERPERMISSION" || tbl == "USERROLE" || tbl == "USERROLEDET")
{
_order = SyncDirectionOrder.DownloadAndUpload;
}
else
{
_order = SyncDirectionOrder.Download;
}
}
_CPubVar._value_I++;
_CPubVar._ProcessText_S = "Sync Tables " + _CPubVar._value_I + " of " + _CPubVar._MaxValue_I;


if (tbl != "_COMPANYINFO")
{
_list1.AddRange(_cSynchronization.Synchronize(tbl + "_SCOP", _order));
}
else
{
if (_CPubVar._IsServerRunning_bool)
{
_list1.AddRange(_cSynchronization.Synchronize(tbl + "_SCOP", SyncDirectionOrder.DownloadAndUpload));
}
}
}
catch (Exception exx)
{
_syncErr.Add(new _CSyncErrors { SyncErrorDateTime = DateTime.Now, SyncErrorMessage = exx.Message, SyncTableAlies = _CTableName._MgetTableAlies(tbl) });
pictureBox1.Visible = label3.Visible = true;
label3.Text = _syncErr.Count.ToString();
Application.DoEvents();
continue;
}
}
thread.Abort();

}

问题:

以上代码一次仅适用于一台 PC 同步(让 Take A)没有错误并完成。

一次同步一台电脑(让 Take B)没有错误并完成。

但是当我尝试同时运行应用程序(A 和 B 同时运行)时,我得到了一些表

Cannot enumerate changes at the RelationalSyncProvider for table 'TableName'

运行状态

PC A      PC B      Result
YES NO No Error
NO YES No Error
YES YES Error

请注意,客户端我的数据库是 2008,服务器端我的数据库是 2012我哪里错了

更新:我在数据库中有 72 个表,下面的错误不是特定的“表名”,它可能是 72 中的任何表,

例如 Table1 给我错误,在同步完成后如果我重新运行应用程序可能不会出现此错误。

Cannot enumerate changes at the RelationalSyncProvider for table 'TableName'

最佳答案

检查超时

八分钟可能不够。尝试将同步命令超时增加到一个荒谬的数字,看看是否是问题所在。

 clientProvider.CommandTimeout = 3000;
serverProvider.CommandTimeout = 3000;

开启追踪

通过添加以下 system.diagnostics 段,为您的应用程序编辑 app.config 文件。它将详细记录到 C:\MySyncTrace.txt

<configuration>
<system.diagnostics>
<switches>
<!--4-verbose.-->
<add name="SyncTracer" value="4" />
</switches>
<trace autoflush="true">
<listeners>
<add name="TestListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="c:\MySyncTrace.txt"/>
</listeners>
</trace>
</system.diagnostics>
</configuration>

我的娱乐

我试图重现您遇到的错误。我创建了您要完成的任务的简化版本。它构建并成功同步了两个 SqlExpress 数据库。

不幸的是,我无法重现错误。这是我使用的设置和之后的测试用例。

模拟数据库创建脚本

USE Master;
GO

IF EXISTS (
SELECT *
FROM sys.databases
WHERE NAME = 'SyncTestServer'
)
DROP DATABASE SyncTestServer
GO

CREATE DATABASE SyncTestServer;
GO

CREATE TABLE SyncTestServer.dbo.Table1 (Column1 VARCHAR(50) PRIMARY KEY)
CREATE TABLE SyncTestServer.dbo.Table2 (Column1 VARCHAR(50) PRIMARY KEY)

INSERT INTO SyncTestServer.dbo.Table1 (Column1)
VALUES ('Server Data in Table1')

INSERT INTO SyncTestServer.dbo.Table2 (Column1)
VALUES ('Server Data in Table2')

IF EXISTS (
SELECT *
FROM sys.databases
WHERE NAME = 'SyncTestClient'
)
DROP DATABASE SyncTestClient
GO

CREATE DATABASE SyncTestClient;
GO

CREATE TABLE SyncTestClient.dbo.Table1 (Column1 VARCHAR(50) PRIMARY KEY)
CREATE TABLE SyncTestClient.dbo.Table2 (Column1 VARCHAR(50) PRIMARY KEY)

INSERT INTO SyncTestClient.dbo.Table1 (Column1)
VALUES ('Client Data in Table1')

INSERT INTO SyncTestClient.dbo.Table2 (Column1)
VALUES ('Client Data in Table2')

模拟控制台应用程序

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization;

namespace StackOverflow_SyncFramework
{
public class _CSyncDetails
{
public int UploadChangesTotal;
public DateTime SyncStartTime;
public int DownloadChangesTotal;
public DateTime SyncEndTime;
}

public class Program
{
static void Main(string[] args)
{
_cSynchronization sync = new _cSynchronization();
sync._MSync();

Console.ReadLine();
}
}

public class _cSynchronization
{
public static int transactionCount;
public static uint BatchSize = 10000;
public static uint MemorySize = 20000;
public const string ServerConnString =
@"Data Source=.\SQLExpress;initial catalog=SyncTestServer;integrated security=True;MultipleActiveResultSets=True;";
public const string ClientConnString =
@"Data Source=.\SQLExpress;initial catalog=SyncTestClient;integrated security=True;MultipleActiveResultSets=True;";

public static List<string> _MGetAllTableList()
{
// I just created two databases that each have the following table
// Synchronization is working
List<string> list = new List<string>()
{
"Table1",
"Table2"
};
return list;
}

public static void SetUp(string _pTableName)
{
// Connection to SQL Server database
SqlConnection serverConn =
new SqlConnection(ServerConnString);
// Connection to SQL client database
SqlConnection clientConn =
new SqlConnection(ClientConnString);

// Create a scope named "product" and add tables to it.
Console.WriteLine(_pTableName);
DbSyncScopeDescription productScope = new DbSyncScopeDescription(_pTableName + "_SCOP");

// Define the Products table.
DbSyncTableDescription productDescription =
SqlSyncDescriptionBuilder.GetDescriptionForTable(_pTableName, serverConn);
// Add the Table to the scope object.
productScope.Tables.Add(productDescription);

// Create a provisioning object for "product" and apply it to the on-premise database if one does not exist.
SqlSyncScopeProvisioning serverProvision = new SqlSyncScopeProvisioning(serverConn, productScope);
serverProvision.ObjectSchema = ".dbo";

serverProvision.SetCreateProceduresForAdditionalScopeDefault(DbSyncCreationOption.Create);
serverProvision.SetCreateTableDefault(DbSyncCreationOption.Skip);
serverProvision.SetCreateProceduresDefault(DbSyncCreationOption.CreateOrUseExisting);
serverProvision.SetCreateTrackingTableDefault(DbSyncCreationOption.CreateOrUseExisting);
serverProvision.SetCreateTriggersDefault(DbSyncCreationOption.CreateOrUseExisting);

if (!serverProvision.ScopeExists(_pTableName + "_SCOP"))
serverProvision.Apply();

// Provision the SQL client database from the on-premise SQL Server database if one does not exist.
SqlSyncScopeProvisioning clientProvision = new SqlSyncScopeProvisioning(clientConn, productScope);

if (!clientProvision.ScopeExists(_pTableName + "_SCOP"))
clientProvision.Apply();

// Shut down database connections.
serverConn.Close();
serverConn.Dispose();
clientConn.Close();
clientConn.Dispose();
}

public static List<_CSyncDetails> Synchronize(string _pScopeName, SyncDirectionOrder _pDirection)
{
// Connection to SQL Server database
SqlConnection serverConn =
new SqlConnection(ServerConnString);

// Connection to SQL client database
SqlConnection clientConn =
new SqlConnection(ClientConnString);

List<_CSyncDetails> _Statics = new List<_CSyncDetails>();

// Perform Synchronization between SQL Server and the SQL client.
SyncOrchestrator syncOrchestrator = new SyncOrchestrator();

// Create provider for SQL Server
SqlSyncProvider serverProvider = new SqlSyncProvider(_pScopeName, serverConn);

// Set the command timeout and maximum transaction size for the SQL Azure provider.
SqlSyncProvider clientProvider = new SqlSyncProvider(_pScopeName, clientConn);

clientProvider.CommandTimeout = serverProvider.CommandTimeout = 500;
//Set memory allocation to the database providers
clientProvider.MemoryDataCacheSize = serverProvider.MemoryDataCacheSize = MemorySize;

//Set application transaction size on destination provider.
serverProvider.ApplicationTransactionSize = BatchSize;

//Count transactions
serverProvider.ChangesApplied +=
new EventHandler<DbChangesAppliedEventArgs>(RemoteProvider_ChangesApplied);

// Set Local provider of SyncOrchestrator to the server provider
syncOrchestrator.LocalProvider = serverProvider;

// Set Remote provider of SyncOrchestrator to the client provider
syncOrchestrator.RemoteProvider = clientProvider;

// Set the direction of SyncOrchestrator session to Upload and Download
syncOrchestrator.Direction = _pDirection;

// Create SyncOperations Statistics Object

SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();
_Statics.Add(new _CSyncDetails
{
UploadChangesTotal = syncStats.UploadChangesTotal,
SyncStartTime = syncStats.SyncStartTime,
DownloadChangesTotal = syncStats.DownloadChangesTotal,
SyncEndTime = syncStats.SyncEndTime
});

// Shut down database connections.
serverConn.Close();
serverConn.Dispose();
clientConn.Close();
clientConn.Dispose();
return _Statics;
}

private static void RemoteProvider_ChangesApplied(object sender, DbChangesAppliedEventArgs e)
{
Console.WriteLine("Changes Applied");
}

public void _MSync()
{
// Define the Products table.
List<string> _Tablelist = new List<string>();
_Tablelist.AddRange(_cSynchronization._MGetAllTableList());

foreach (string tbl in _Tablelist)
{
SetUp(tbl);
_cSynchronization.Synchronize(tbl + "_SCOP", SyncDirectionOrder.DownloadAndUpload);
}
}
}
}

为测试前后选择语句

SELECT * 
FROM SyncTestServer.dbo.Table1

SELECT *
FROM SyncTestServer.dbo.Table2

SELECT *
FROM SyncTestClient.dbo.Table1

SELECT *
FROM SyncTestClient.dbo.Table2

同步前

这是同步前的数据库状态。

enter image description here

同步后

这是后来的状态。因此,同步似乎有效。

enter image description here

重新尝试删除服务器和三个并发同步

这是远程数据库的连接字符串。

public const string ServerConnString =
@"data source=x0x0x0x0x0x.database.windows.net,1433;initial catalog=SyncTestServer01;user id=xoxoxox@xoxoxox;password=xoxoxoxoxox;MultipleActiveResultSets=True;";

这是模拟三个并发同步的修改。

public class Program
{
public static string[] ClientConnString = new string[]
{
@"Data Source=.\SQLExpress;initial catalog=SyncTestClient01;integrated security=True;MultipleActiveResultSets=True;"
,@"Data Source=.\SQLExpress;initial catalog=SyncTestClient02;integrated security=True;MultipleActiveResultSets=True;"
,@"Data Source=.\SQLExpress;initial catalog=SyncTestClient03;integrated security=True;MultipleActiveResultSets=True;"
};

static void Main(string[] args)
{
foreach (var connString in ClientConnString)
{
Action action = () =>
{
_cSynchronization sync = new _cSynchronization();
sync._MSync(connString);
};
Task.Factory.StartNew(action);
}

Console.ReadLine();
}
}

恐怕我无法重现您遇到的错误。请打开跟踪,然后将跟踪结果发布到您的问题中。这样我们就可以分析跟踪并查看问题所在。

关于c# - 微软同步框架 : Cannot enumerate changes at the RelationalSyncProvider for table 'Table Name' ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29298166/

25 4 0