1.专题
1.1 简介
由于我们的第一篇技术文章的成功,可以在这里找到 此处 我们决定继续。这一次我们将看看如何以一种最简单的方式实现Exchange和Salesforce之间的集成。我们将使用SQL查询。
对于集成,我们使用CB Linked Server for Enterprise Applications。请向我们申请免费试用该产品。
2.情景要求
这里需要的集成方案是在本地数据库联系人表、Exchange 365联系人和SalesForce联系人之间进行同步,并从本地数据库表立即复制到这2个目标系统。这对于离线备份联系人或创建数据仓库或其他一些原因可能很有用。
3.基本工作流程
3.1 配置CB查询分析器
第一步,确保能够连接到目标系统(在我们的方案中为 Exchange 和 SalesForce);最简单的方法是通过 CB 查询分析器。在这里,我已经通过管理工具配置了我的 ConnectBridge 服务器,以便通过创建所需的组和用户连接到 MS Exchange 365 和 SalesForce。我创建了一个名为“马丁”,密码为“1234”.该用户拥有连接 Exchange 365 和 SalesForce 的权限。现在,我将在查询分析器中为每个目标系统创建 2 个连接,并确保连接成功。.

图1:账户管理

图2:组和用户管理

图3.查询分析器的连接查询分析器的连接
3.2 测试你的声明
如上图所示,我们已经成功配置并连接到两个目标系统。现在我们可以测试我们的语句
3.2.1 Exchange 触点
在我的Exchange账户上,我有3个联系人,如下图所示。

图4:Exchange触点
现在我们要测试4个基本操作SELECT、INSERT、UPDATE和DELETE。
1.选择联系人
执行下面的语句应该可以得到图5所示的3个触点。
SELECT [GivenName],[SurName],[Email1EmailAddress] FROM [Contact]。

图5:选择联系人
2.插入一个触点
执行下面的语句应该插入一个新的联系人,如图6所示。
INSERT INTO Contact([GivenName], [SurName], [Email1EmailAddress]) VALUES ('Peter', 'K.', 'peter@gmail.com')。

图6:插入新触点
3.更新联系人
执行下面的语句应该更新我们之前插入的联系人的姓氏,如图7所示。
UPDATE Contact SET [SurName] = 'Keys' WHERE [Email1EmailAddress] LIKE 'peter@gmail.com';

图 7: 更新联系人
4.4. 删除联系人
执行下面的语句应该会删除新插入的联系人,如图8所示。
DELETE FROM Contact WHERE [Email1EmailAddress] LIKE 'peter@gmail.com';

图8:删除联系人
3.2.2 Salesforce联系人
在我的SalesForce账户上,我有17个联系人,如下图所示

图9:SalesForce联系人
现在我们要测试同样的4个基本操作SELECT、INSERT、UPDATE & DELETE。
1.选择联系人
执行下面的语句应该可以得到图10所示的17个联系人。
SELECT [FirstName],[LastName],[Email] FROM [Contact]。

图 10: 选择联系人
2.插入一个触点
执行下面的语句应该插入一个新的联系人,如图11所示。
INSERT INTO Contact([Firstname], [LastName], [Email]) VALUES ('Peter', 'K.', 'peter@gmail.com');

图11:插入新触点
3.更新联系人
执行下面的语句应该更新我们之前插入的联系人的姓氏,如图12所示。
UPDATE Contact SET [LastName] = 'Keys' WHERE [Email] = 'peter@gmail.com';

图 12: 更新联系人
4.4. 删除联系人
执行下面的语句应该会删除新插入的联系人,如图13所示。
DELETE FROM Contact WHERE [Email] = 'peter@gmail.com';

图13:删除联系人
3.3 复制连接和声明
现在我们知道,我们能够从Exchange和SalesForce中选择、更新、插入和删除联系人。现在我们需要做的是从Query Analyzer中复制连接字符串和我们测试过的语句,以便以后在MS SQL Server解决方案中使用它们。
要从查询分析器中复制连接,我们只需要右键点击该连接,点击编辑并进入高级选项卡,从那里复制文本,如下图14所示。

图14:从查询分析器复制连接字符串
以下是我对两个目标系统的连接字符串。
Exchange
Driver={Media Gateway ODBC Driver};impl='CORBA';host='localhost';port='8087';acc='ACC_EXCH365_CU7';uid='martin';pwd='1234'
SalesForce
Driver={Media Gateway ODBC Driver};IMPL=CORBA;HOST='localhost';PORT='8087';ACC='ACC_SALF_CBD';UID='martin';PWD='1234'
现在我们准备打开MS SQL Server,开始实施我们的SQL Server集成解决方案。
4.解决方案演练
4.1 MS SQL Server
为了能够通过SQL Server Linked Server功能与外部数据源合作,我们需要进行以下配置。
1.启动Microsoft SQL Server Management Studio,使用windows认证或用户名和密码登录,如下图15所示。

图15:MS SQL Server管理工作室登录屏幕

图16:MSDASQL属性
2.导航到 Sever Objects -> Linked Servers -> Providers -> MSDASQL。 通过展开相应的节点,如上图16所示。右键点击 MSDASQL - Microsoft Data Access SQL - 并选择 属性 以显示图17中的对话框

图17:MSDASQL属性设置
3.3. 我们必须确保检查以下设置/选项:
a. 仅为零级:出于安全考虑,我们必须确保只支持符合0级OLE DB接口的OLE DB提供者。
b. 允许进程中数据提供程序:允许数据提供程序--“外部数据源”--作为进程内服务器实例化--“与 MS SQL Server 位于同一进程”。我们需要这样做,以避免在 MS SQL Server 和提供程序之间传递身份验证信息,并能处理 varchar(max)、nvarchar(max)、varbinary(max)、文本、ntext 或图像等数据类型。例如,如果不启用该选项,我们就无法从 Exchange 获取图像类型的数据并将其插入 MS SQL Server 数据库。.
4.现在,我们需要启用 MS SQL Server 连接到外部提供程序并执行查询,以便从使用 OLEDB 的外部提供程序(我们称之为 “OLEDB")中查询数据。“外部OLEDB数据源”.我们将分三步走:
a.我们需要单击新建查询按钮,打开一个新的查询窗口,如下图 18 所示。哪个数据库处于活动状态并不重要,因为我们要做的事情会影响整个 MS SQL Server 安装,进而影响其中的每个数据库。如下图所示,我将 “master ”作为活动/目标数据库

图18:MS SQL Server查询分析器
b.我们需要重新配置 MS SQL Server,以便更改/配置其高级选项。为此,我们将执行一个名为 “sp_configure ”的存储过程(这是一个预装的系统存储过程),并将 “显示高级选项 ”这一选项设置为 1。为此,我们键入 “exec sp_configure 'show advanced options', 1; reconfigure”,然后按 F5 执行。如果一切顺利,你应该会收到类似下图 19 的信息
图19:MS SQL Server - 显示高级选项

c.现在,我们需要允许 MS SQL Server 查询这些“......"。“外部OLEDB数据源”使用一种名为“特设分布式查询”.默认情况下,MS SQL Server 不允许使用 “Ad Hoc Distributed Queries(临时分布式查询)”,因此我们需要重新配置这个高级选项--这也是我们进行上一步操作的原因--通过执行存储过程 “sp_configure”,传递设置 “Ad Hoc Distributed Queries ”和值 1 来启用它。如果一切顺利,在执行 “exec sp_configure 'Ad Hoc Distributed Queries', 1; reconfigure”(执行 sp_configure 'Ad Hoc Distributed Queries',1; 重新配置)后,应该会收到与下图 20 类似的信息。”

图20:MS SQL Server - 启用临时分布式查询
现在我们可以添加任意数量的Linked Server,因为我们的MS SQL Server已经正确配置为允许这样做。
4.2 配置MS Exchange链接服务器
1.导航到 Sever对象 -> 链接服务器.右键点击 链接服务器 并选择 新的链接服务器 如下图21所示

图21:MS SQL Server - 添加新的链接服务器
2.在新建链接服务器对话框中,如下图22所示,需要提供以下内容。
a. 链接服务器名称:可以是任何有效的名称,我选择Exchange365_CU7。
b. 供应商:必须是 “Microsoft OLE DB Providers for ODBC Drivers”,因为 ConnectBridge 使用的是 ODBC。.
c. 提供者字符串在这里,我们粘贴之前从查询分析器复制的连接字符串。

图22:MS SQL Server - 配置新的链接服务器 - 常规
3.现在,我们需要在使用/访问 MS SQL Server 的用户和使用/访问 CB 的用户之间建立关系。使用 MS SQL Server 的用户称为本地登录用户(在我们的方案中为 “sa”),使用/访问 CB 的用户称为远程用户(在我们的方案中为 Martin,登录名为 martin)。这就是我们要配置的,为此我们点击“ "。“安全性”选项卡,显示下图 23 中的对话框

图 23: MS SQL Server - 配置新的链接服务器 - 安全性
4.显示上述对话框后,单击 "添加 "按钮,按照约定输入本地登录名和远程用户名。如图 24 所示

图24:MS SQL Server - 配置新的链接服务器 - 登录
5.好了,我知道你想关闭对话框,但等等!我们还需要做一个步骤。现在我们需要转到“服务器选项”左侧的"...... "选项卡显示下图 25 中的对话框,并启用 2 项功能
a. RPC启用某项安全功能,当我们使用一些传统的功能时,我们需要该功能,称为 远程服务器 - 现在不用担心 - 这样就可以在 CB 和 MS SQL Server 之间进行登录验证了
b. RPC Out:启用“远程过程调用”功能,因为我们需要允许我们的存储过程能够远程运行

图25:MS SQL Server - 配置新的链接服务器 - 服务器选项
6.现在我们点击好,就完成了!是的!我们配置了MS SQL Server连接到Exchange。我们配置了MS SQL Server来连接Exchange。现在我们可以在MS SQL Server中看到Exchange平台作为一个数据库,我们可以看到名为Contacts的表,我们可以显示Exchange的联系人列表,所有这些,都不需要访问Exchange数据库,你可以在下面的图26中看到。

图26:MS SQL Server - 链接服务器配置成功
4.3测试MS Exchange链接服务器
在开发集成方案之前,我们需要确保能够通过新配置的Linked Server对MS Exchange进行基本数据操作。
1.选择联系人
执行下面的语句应该可以得到MS Exchange的3个联系人。
SELECT GivenName, SurName, Email1EmailAddress FROM EXCHANGE365_CU7...联系人。
为什么要加上“...”?因为它遵循的语法是 SERVER.DATABASE.SCHEMA.TABLE,如上图 26 所示,我们的服务器是 Exchange365_CU7,数据库是 “无名”,模式是 “无名”,最后我们的表是 Contacts。.

图27:选择联系人
2.插入一个触点
执行下面的语句应该插入一个新的联系人。
EXEC ('INSERT INTO Contact([GivenName], [SurName], [Email1EmailAddress])
VALUES ("Peter", "K.", "peter@gmail.com");' ) AT EXCHANGE365_CU7;

图28.插入新触点插入新触点
3.更新联系人
执行下面的语句应该更新我们之前插入的联系人的姓氏
EXEC('UPDATE Contact SET [SurName] = "Keys" WHERE [Email1EmailAddress] LIKE
"peter@gmail.com";') at exchange365_cu7;

图29:更新联系人
4.4. 删除联系人
执行下面的语句应该删除新插入的联系人。
EXEC ('DELETE FROM Contact WHERE [Email1EmailAddress] LIKE
"peter@gmail.com";') at exchange365_cu7;

图30:删除联系
4.4 配置SalesForce关联服务器
我们将按照 “4.2 配置 MS Exchange 链接服务器 ”一节中的步骤进行操作,当然,我们将使用 SalesForce 的连接字符串。按照这些步骤操作后,链接服务器应能成功配置,如下图所示。.

图31.SalesForce链接服务器配置成功SalesForce关联服务器配置成功
4.5测试Salesforce关联服务器
就像我们之前也使用MS Exchange链接服务器一样,我们需要确保能够通过SalesForce链接服务器来执行基本数据操作任务。
为了缩短指南,下图32是测试以下所有语句
1.选择联系人
执行下面的语句应该可以得到SalesForce的联系人。
SELECT GivenName, SurName, Email1EmailAddress FROM EXCHANGE365_CU7...联系人。
2.插入一个触点
执行下面的语句应该插入一个新的联系人。
EXEC ('INSERT INTO Contact([GivenName], [SurName], [Email1EmailAddress])
VALUES ("Peter", "K.", "peter@gmail.com");' ) AT EXCHANGE365_CU7;
3.更新联系人
执行下面的语句应该更新我们之前插入的联系人的姓氏
EXEC('UPDATE Contact SET [SurName] = "Keys" WHERE [Email1EmailAddress] LIKE
"peter@gmail.com";') at exchange365_cu7;
4.4. 删除联系人
执行下面的语句应该删除新插入的联系人。
EXEC ('DELETE FROM Contact WHERE [Email1EmailAddress] LIKE
"peter@gmail.com";') at exchange365_cu7;

图32.测试SalesForce链接服务器测试SalesForce链接服务器
4.6 本地数据库表
从这里开始,我们需要在我们的本地MS SQL Server上有一个实际的本地数据库,如果你已经有一个,那么你可以使用,否则我们需要创建一个新的数据库。如果你已经有一个,那么你可以使用,否则我们需要创建一个新的数据库。我创建了一个名为ConnectingSoftware的数据库,其中有1个名为LocalContacts的表。在该表中只有一条记录,如下图33所示。
图33.本地联系人表当地联系人表
4.7 复制表触发

我们解决方案的第一步是将本地数据库表中的变化复制到SalesForce和Exchange中,我们将通过表触发器来实现。
触发器的SQL脚本如下所示。
CREATE TRIGGER [dbo].[trgSyncContact].
ON [dbo].[LocalContacts]
在插入、更新、删除之后。
AS
BEGIN
声明 @Operation varchar(50)
声明 @FirstName nvarchar(max)
声明 @LastName nvarchar(max)
声明 @Email varchar(255)
声明 @Deleted_FirstName nvarchar(max)
声明 @Deleted_LastName nvarchar(max)
声明 @Deleted_Email varchar(255)
IF COLUMNS_UPDATED() > 0
BEGIN
--如果我们更新了列,那么我们就插入或删除了一个列。
记录
IF EXISTS (SELECT * FROM DELETED)
BEGIN
--如果我们删除了数值,那么这是一个更新操作
SELECT @FirstName = inserted.FirstName, @LastName =......。
inserted.LastName, @Email = inserted.Email,
@Deleted_FirstName = deleted.FirstName,
@Deleted_LastName = deleted.LastName, @Deleted_Email = 删除的电子邮件。
删除.电子邮件
从删除的、插入的
--销售力量
执行 ('UPDATE Contact SET FirstName = ?, LastName = ?, Email = ?
WHERE FirstName = ? and LastName = ? and Email = ?
@FirstName, @LastName, @Email, @Deleted_FirstName,
@Deleted_LastName, @Deleted_Email)在SALESFORCE_CBD。
--Exchange
EXEC('UPDATE Contact SET GivenName = ? ,SurName = ?
Email1EmailAddress = ?WHERE GivenName = ?
和Email1EmailAddress=?',@FirstName,@LastName。
@电子邮件,@删除的名字,@删除的姓氏。
@Deleted_Email)在EXCHANGE365_CU7。
END
ELSE
BEGIN
--如果不是更新操作,那么就是插入操作
SELECT @FirstName = 名字, @LastName = 姓氏, @Email = 电子邮件。
电子邮件
从插入的
--销售力量
执行('插入到联系人(名、姓、电子邮件)中的值)
(?,?,?)', @FirstName, @LastName, @Email) 在
SALESFORCE_CBD;
--MS Exchange
EXEC('插入到联系人(GivenName,SurName。
Email1EmailAddress)值(?,?,?)',@FirstName,
@LastName, @Email)在EXCHANGE365_CU7。
END
结束
ELSE
BEGIN
--如果操作不是更新/插入,那么就是删除。
SELECT @Deleted_Email = Email FROM deleted
--销售力量
Exec ('Delete From Contact Where Email = ?', @Deleted_Email) at
SALESFORCE_CBD;
--MS Exchange
Exec ('Delete from Contact Where Email1EmailAddress = ?'.@Deleted_Email) at EXCHANGE365_CU7;。
@Deleted_Email)在EXCHANGE365_CU7;
最后,在EXCHANGE365_CU7; END
结束
警告:执行上述脚本后,在同步两个目标系统(Exchange 和 SalesForce)和本地数据库之前,我们不应该从本地数据库表中插入任何内容,否则可能会意外重复记录,因为这里的逻辑没有检查目标系统中是否已经存在新记录。.
4.8 同步化存储程序
我们解决方案的第二步是在MS Exchange、SalesForce和我们的本地联系人表之间进行同步,这样每个系统都会有相同的联系人集。
为此,我们要写一个存储过程。该存储过程的逻辑是:
1.重要的是要禁用我们在上面创建的触发器,“因为我们正在进行同步,所以一定不能启用触发器实现的自动复制功能”。”
2.SalesForce和我的数据库之间的同步
使用联系人的电子邮件地址作为匹配键;SalesForce 中是否有联系人,但不在我的本地联系人表中?
a.是:将联系人添加到我的本地联系人表中
b.否: 更新本地联系人表中联系人的名和姓
3.MS Exchange与我的数据库之间的同步。
使用联系人的电子邮件地址作为匹配键;Exchange 上是否有联系人,但不在我的本地联系人表中?
a.是:将联系人添加到我的本地联系人表中
b.否: 更新本地联系人表中联系人的名和姓
此时,我的本地联系人表中除了有原来的记录外,还有来自SalesForce和MS Exchange的所有联系人。现在,我们需要通过其他目标系统的联系人和本地数据库来更新每个目标系统的联系人
4.更新SalesForce上的联系人(通过Exchange和我的本地表的联系人)。
使用联系人的电子邮件地址作为匹配键;我的本地联系人表中有联系人,但 SalesForce 中没有?
a.是:将联系人添加到SalesForce
b.否:更新 SalesForce 上联系人的名和姓
5.更新Exchange上的联系人(通过SalesForce和我的本地表的联系人)
使用联系人的电子邮件地址作为匹配键;我的本地联系人表中有联系人,但 Exchange 中没有?
a.是:在MS Exchange中添加联系人。
b.否:更新 Exchange 上联系人的名和姓
6.现在,我们可以启用我们之前禁用的触发器,这样自动复制就恢复了ON。
下面的SQL脚本将实现上面讨论的逻辑。
CREATE PROCEDURE [dbo].[uspInitSync]。
-- 在此添加存储程序的参数
AS
BEGIN
-- 增加了SET NOCOUNT ON,以防止出现额外的结果集。
-- 干扰SELECT语句。
设置NOCOUNT ON。
--禁用触发器,这样,当从SalesForce插入时,我们就不会出现在
-- 再次向SalesForce添加联系人
DISABLE TRIGGER [trgSyncContact] ON LocalContacts;
--将SalesForce的记录合并到LocalDB。
DECLARE @ImportedContacts Table(FirstName nvarchar(max), LastName)
nvarchar(max), Email varchar(255))。
--以SalesForce为源,在本地数据库中更新/插入联系人。
MERGE LocalContacts AS target
USING (SELECT FirstName, LastName, Email FROM SalesForce_CBD...Contact)
AS源
ON (target.Email LIKE source.Email)
当匹配时,然后
UPDATE SET FirstName = source.FirstName,LastName = LastName。
来源.姓氏
当不匹配时,则
INSERT (FirstName, LastName, Email)
VALUES (source.FirstName, source.LastName, source.Email)
OUTPUT inserted.FirstName,inserted.LastName,inserted.Email。
INTO @ImportedContacts;
--显示从SalesForce插入到LocalDB中的联系人。
从@ImportedContacts中选择*。
--以Exchange为源,在本地数据库中更新/插入联系人。
MERGE LocalContacts AS target
使用(SELECT GivenName, SurName, Email1EmailAddress FROM
EXCHANGE365_CU7...Contact) AS source
ON (target.Email LIKE source.Email1EmailAddress)
当匹配时,然后
UPDATE SET FirstName = source.GivenName,LastName =
来源.SurName
当不匹配时,则
INSERT (FirstName, LastName, Email)
VALUES (source.GivenName, source.SurName.)
source.Email1EmailAddress)
OUTPUT inserted.FirstName,inserted.LastName,inserted.Email。
INTO @ImportedContacts;
--使用表格变量显示插入的联系人
从@ImportedContacts中选择*。
--现在将所有内容复制到SalesForce和Exchange,以便他们有准确的副本。
--在LocalDB与所有系统同步后,从LocalDB中获取。
--我必须使用cursour和if,因为使用insert....select_0where不是
--exists不能用于远程表,合并也不能用于远程表。
--远程表
Declare @FirstName nvarchar(max)
声明 @LastName nvarchar(max)
声明 @Email varchar(255)
声明 @SQL nvarchar(max)
DECLARE Contacts_cursor CURSOR FAST_FORWARD FOR
SELECT FirstName, LastName, Email from LocalContacts;
打开联系人_光标
FETCH NEXT FROM Contacts_cursor INTO @FirstName, @LastName, @Email。
WHILE @@FETCH_STATUS = 0
BEGIN
如果存在(SELECT Email1EmailAddress FROM EXCHANGE365_CU7...Contact)
WHERE Email1EmailAddress LIKE @Email)
EXEC ('UPDATE Contact SET GivenName = ?, SurName = ?)在哪里
Email1EmailAddress = ?', @FirstName, @LastName, @Email)
在EXCHANGE365_CU7。
ELSE
EXEC('插入到联系人(GivenName,SurName。
Email1EmailAddress)值(?,?,?)',@FirstName,
@姓,@Email)在EXCHANGE365_CU7。
IF EXISTS (SELECT Email FROM SalesForce_CBD...Contact WHERE Email LIKE)
@电子邮件)
执行('UPDATE Contact SET FirstName = ?, LastName = ?在哪里
电子邮件=?', @FirstName, @LastName, @Email)。
SalesForce_CBD。
ELSE
执行('插入到联系人(名、姓、电子邮件)中的值)
(?,?,?)', @FirstName, @LastName, @Email) 在
SalesForce_CBD。
FETCH NEXT FROM Contacts_cursor INTO @FirstName, @LastName, @Email。
结束
关闭Contacts_cursor.DEALLOCATE Contacts_cursor;。
DEALLOCATE Contacts_cursor。
--启用触发器,以便任何修改都能反映在在线LOB中。
ENABLE TRIGGER [trgSyncContact] ON LocalContacts;
结束
5.解决办法在行动
第一步是运行同步存储过程 “uspInitSync”,如下图所示,存储过程执行无误。.

图34:运行同步存储过程
我们还可以看到,MS Exchange中增加了新的联系人。

图35.MS Exchange的更新MS Exchange的最新情况
并向SalesForce添加新的联系人

图36:关于SalesForce的更新
而我们的本地数据库表现在有了新的联系人。

图37:本地联系人表中的更新
我们也可以看到自动复制的操作方式
1.从本地数据库中插入联系人,从SalesForce和Exchange中删除该联系人

图38:插入复制
2.更新本地数据库中的联系人,会在SalesForce和Exchange中更新。

图39:更新复制
3.从本地数据库中删除联系人,从SalesForce和Exchange中删除。

图40:删除复制
6.关于解决方案的说明
我们试图让解决方案的逻辑尽可能的简单,但是为了更好的性能和更复杂的功能,逻辑还可以进一步改进和调整。
您可以在以下产品页面找到更多关于该产品的信息。 CB Linked Server for Enterprise Applications.
