在现代应用程序中,实时数据更新是一个重要的需求。本文将介绍如何使用Oracle的数据库变更通知技术与Windows Communication Foundation (WCF)进行集成,实现当数据库中的数据发生变化时,能够通过WCF服务实时通知客户端。这种技术不仅可以提高应用程序的性能,还可以提供更好的可扩展性,相比于定时轮询数据库以获取最新数据的方法更为高效。
在尝试寻找一个示例,展示如何使用WCF技术订阅Oracle 10g/11g数据库变更通知技术时,发现并没有找到使用ODP.NET的示例。因此,决定创建一个示例,以帮助需要解决类似问题的开发者。
在WCF服务中,关键的一点是要注意CallbackContract
属性,它指定了WCF服务应该使用哪个契约来回调客户端,以及两个契约上的IsOneWay
属性,用于指定异步双向契约。
每次数据发生变化时,都会通过回调向客户端发送新的数据集。客户端订阅数据,但在Subscribe
调用中不会返回任何数据,但WCF服务会立即通过提供的回调调用客户端,提供当前数据状态的数据集。之后,每次数据发生变化,WCF服务都会再次通过回调向客户端发送新的数据集。
[ServiceContract(
Name = "WCFQNTableSubscribe",
Namespace = "WCFOracleDatabaseChangeNotification",
CallbackContract = typeof(IWCFQNTableCallback),
SessionMode = SessionMode.Required)]
public interface IWCFQNTableSubscribe
{
[OperationContract(IsOneWay = true)]
void Subscribe();
}
数据集通过此契约发送回客户端。
public interface IWCFQNTableCallback
{
[OperationContract(IsOneWay = true)]
void Callback(DataSet data);
}
有一个名为WCFQNTableSubscription
的类,它实现了Subscribe
方法。
此方法将调用客户端注册到服务器。然后,它通过传递客户端的回调信息来实例化一个名为WCFQNRequestState
的类。最后,它调用类的SubmitDataRequest
方法,以注册硬编码查询,以便在Oracle数据库中发送任何INSERT、UPDATE、DELETE等更改的通知,然后刷新前端的数据网格。
public void Subscribe()
{
IWCFQNTableCallback callback = OperationContext.Current.GetCallbackChannel();
WCFQNRequestState subscription = new WCFQNRequestState(callback);
subscription.SubmitDataRequest();
}
有一个内部类名为WCFQNRequestState
,它由一个接受客户端回调信息的构造函数组成。
private IWCFQNTableCallback _callback;
public WCFQNRequestState(IWCFQNTableCallback callback)
{
_callback = callback;
}
它连接到Oracle,并使用OracleDependency实例进行Oracle数据库变更通知。它添加事件处理程序来处理通知。当数据库发送通知消息时,只有当注册查询的行被更新、插入、删除等时,OnMyNotification
方法才会被调用。它还将查询结果集填充到数据集中,并通过回调向WCF客户端返回,以刷新数据网格。
public void SubmitDataRequest()
{
string constr = "your connection string for Oracle Database";
string sqlSelect = "select * from sched_generation_process ";
string sql = sqlSelect + "where sched_gen_sid = 3";
string tablename = "sched_generation_process";
DataSet ds = new DataSet();
OracleConnection con = new OracleConnection(constr);
OracleCommand cmd = new OracleCommand(sql, con);
con.Open();
cmd.AddRowid = true;
OracleDependency dep = new OracleDependency(cmd);
cmd.Notification.IsNotifiedOnce = false;
dep.OnChange += new OnChangeEventHandler(dep_OnChange);
OracleDataAdapter da = new OracleDataAdapter(cmd);
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
da.Fill(ds, tablename);
_callback.Callback(ds);
}
当客户端(注:包含了3个客户端项目,分别为TCP、HTTP和IPC)按下“订阅按钮”时,客户端会调用WCF服务的Subscribe
方法。
WCF服务的Subscribe
方法通过存储客户端回调详细信息来注册客户端。然后,它将客户端的CALLBACK信息传递给WCFQNRequestState
类,并调用一个名为SubmitDataRequest
的方法。
SubmitDataRequest
打开与Oracle的连接。然后,如果结果发生变化,它将注册通知与命令对象。当一个OracleDependency
实例绑定到一个OracleCommand
实例时,会创建一个OracleNotificationRequest
并设置在OracleCommand
的Notification
属性中。这表明后续执行命令将注册通知。
允许数据库中的变更通知处理程序在第一次数据库更改后仍然持续。
cmd.Notification.IsNotifiedOnce = false;
然后,它添加事件处理程序来处理通知。当数据库发送通知消息时,OnMyNotification
方法将被调用。最后,当前结果作为查询的数据集通过客户端回调方法返回,然后数据集绑定到数据网格。
现在,可以看到数据网格中的结果集。接下来,将登录到SqlDeveloper工具,打开Oracle数据库模式,然后打开一个表并手动更新一些行。
更新1行或多行后,客户端会立即通过数据库变更通知系统得到通知。数据网格会用新数据刷新。
去尝试一下,并享受其中的乐趣。