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), text, ntext, or image)。如果不启用这个选项,我们将无法从Exchange获得图像类型的数据--例如--并将其插入到我们的MS SQL Server数据库。
4.现在,我们需要启用MS SQL Server连接到外部提供者,并执行查询,以查询来自使用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 "后,你应该得到一个类似于图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可以看出,我们的Server是Exchange365_CU7,我们的数据库是 "无名",我们的schema是 "无名",最后我们的表是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 结束
警告:在执行上述脚本后,我们不应该从本地数据库表中插入任何东西,直到我们的2个目标系统(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.