COM+应用层和SQL数据库不在同一台电脑上的事务问题(300分)

  • 主题发起人 主题发起人 冰极
  • 开始时间 开始时间

冰极

Unregistered / Unconfirmed
GUEST, unregistred user!
我用delphi写的mts组件,TMtsDataModule中用ADO连接远程SQL数据库,将数据对象(TMtsDataModule)的事务模型设成需要事务,业务对象(TMTSAutoObject)设为支持事务,然后在业务对象中调用数据对象,如果sql数据库和应用层在同一台电脑上的话就可以正确执行,如果sql数据库和应用层不在在同一台电脑上,就会提示如下错误:
“新事务不能登记到指定的事务处理器中”。
我的系统环境是:windows2003+delphi7.是不是与系统环境配置有关呀?
 
在同一局域网就可以,是不是你的代码有问题,帖出来看一下
 
连接本机的数据库是可以的,连接局域网的其他台机子的数据库就不行,代码如下:
//****************************数据对象**************************************
unit CommonDOImpl;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComServ, ComObj, VCLCom, StdVcl, bdemts, DataBkr, DBClient,
MtsRdm, Mtx, SystemM_TLB, Provider, DB, ADODB,Variants;
type
TCommonDO = class(TMtsDataModule, ICommonDO)
Adoconn_Common: TADOConnection;
Adoqry_ExeSQL: TADOQuery;
dsp_ExeSQL: TDataSetProvider;
Adoqry_Common: TADOQuery;
dsp_Common: TDataSetProvider;
procedure MtsDataModuleActivate(Sender: TObject);
procedure MtsDataModuleDeactivate(Sender: TObject);
procedure MtsDataModuleCreate(Sender: TObject);
private
{ Private declarations }
protected
class procedure UpdateRegistry(Register: Boolean;
const ClassID, ProgID: string);
override;
function GetDataBySql(const SqlText: WideString): OleVariant;
safecall;
function GetOneBySql(const SqlText: WideString;
out MsgError: WideString): OleVariant;
safecall;
public
{ Public declarations }
end;

var
CommonDO: TCommonDO;
implementation
{$R *.DFM}
class procedure TCommonDO.UpdateRegistry(Register: Boolean;
const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
end else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;

function TCommonDO.GetDataBySql(const SqlText: WideString): OleVariant;
begin
try
Adoqry_ExeSQL.Close;
Adoqry_ExeSQL.SQL.Clear;
Adoqry_ExeSQL.SQL.Add(SqlText);
Adoqry_ExeSQL.Open;
Result := dsp_ExeSQL.Data;
SetComplete;
Except
SetAbort;
end;
end;

function TCommonDO.GetOneBySql(const SqlText: WideString;
out MsgError: WideString): OleVariant;
var
i : Integer;
begin
try
Adoqry_ExeSQL.Close;
Adoqry_ExeSQL.SQL.Clear;
Adoqry_ExeSQL.SQL.Add(SqlText);
Adoqry_ExeSQL.Open;
if Adoqry_ExeSQL.RecordCount=0 then
Raise Exception.Create('没有找到合适的记录');
if Adoqry_ExeSQL.RecordCount>1 then
Raise Exception.Create('没有找到合适的记录');
Result := VarArrayCreate([0,Adoqry_ExeSQL.RecordCount-1],VarVariant);
for i := 0 to Adoqry_ExeSQL.RecordCount - 1do
// Iterate
Result := Adoqry_ExeSQL.Fields.Value;
SetComplete;
Except
on E: Exceptiondo
begin
MsgError := E.Message;
SetAbort;
end;
end;
end;

procedure TCommonDO.MtsDataModuleActivate(Sender: TObject);
begin
Adoconn_Common.Connected := True;
end;

procedure TCommonDO.MtsDataModuleDeactivate(Sender: TObject);
begin
Adoconn_Common.Connected := False;
end;

procedure TCommonDO.MtsDataModuleCreate(Sender: TObject);
var
FileName : array[0..255] of Char;
SystemPath : string;
begin
GetModuleFileName(hInstance , FileName , 255);
SystemPath := ExtractFilePath(FileName);
try
Adoconn_Common.Connected := False;
Adoconn_Common.ConnectionString := 'FILE NAME='+SystemPath+'Data.udl';
Except
on e: Exceptiondo
begin
Application.HandleException(Sender);
Raise;
end;
end;
end;

initialization
TComponentFactory.Create(ComServer, TCommonDO,
Class_CommonDO, ciMultiInstance, tmApartment);
end.

//****************************业务对象**************************************
unit SystemMBOImpl;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
ActiveX, Mtsobj, Mtx, ComObj, SystemM_TLB, StdVcl;
type
TSystemMBO = class(TMtsAutoObject, ISystemMBO)
private
ICommonDObject : ICommonDO;
protected
//通用库
function GetDataBySql(const SqlText: WideString): OleVariant;
safecall;
function GetOneBySql(const SqlText: WideString;
out MsgError: WideString): OleVariant;
safecall;
end;

implementation
uses ComServ;

function TSystemMBO.GetDataBySql(const SqlText: WideString): OleVariant;
begin
try
OleCheck(ObjectContext.CreateInstance(CLASS_CommonDO,IID_ICommonDO,
ICommonDObject));
Result := ICommonDObject.GetDataBySql(SqlText);
SetComplete;
except
SetAbort;
Raise;
end;
end;


function TSystemMBO.GetOneBySql(const SqlText: WideString;
out MsgError: WideString): OleVariant;
begin
try
OleCheck(ObjectContext.CreateInstance(CLASS_CommonDO,IID_ICommonDO,
ICommonDObject));
Result := ICommonDObject.GetOneBySql(SqlText,MsgError);
SetComplete;
except
SetAbort;
Raise;
end;
end;


initialization
TAutoObjectFactory.Create(ComServer, TSystemMBO, Class_SystemMBO,
ciMultiInstance, tmApartment);
end.
 
没人碰到这种问题吗..................................
 
估计没有人碰到
 
终于搞定了他了,不敢独享,共享给大家咯^_^
“新事务不能登记到指定的事务中”的解决方案
在开发分布式数据库软件时,经常碰到下面的错误:
服务器: 消息 7391,级别 16,状态 1,行 6
该操作未能执行,因为 OLE DB 提供程序 'SQLOLEDB' 无法启动分
布式事务。
[OLE/DB provider returned message: 不能在指定的事务处理器中
获得新事务。]
-----------------------------------------
服务器: 消息 8520,级别 20,状态 1,行 8
内部 MSDTC 事务的提交失败: Result Code = 0x8004d019。
连接中断
-----------------------------------------
搜索了网上类似问题的解决方案,都建议采用下面的方法(方法一):
1、运行 regedt32,浏览至 HKEY_LOCAL_MACHINE oftware/Microsoft/MSDTC。
添加一个 DWORD 值 TurnOffRpcSecurity,值数据为 1。
2、重启MS DTC服务。
3、打开“管理工具”的“组件服务”。
a. 浏览至"启动管理工具"。 b. 选择"组件服务"。 c. 展开"组件服务"树,然后展开"我的电脑"。 d. 右键单击"我的电脑",然后选择"属性"。 在 MSDTC 选项卡中,确保选中了下列选项:
网络 DTC 访问 网络管理 网络事务XA 事务
另外,"DTC 登录帐户"一定要设置为"NT Authority/NetworkService"。4、重启MS DTC服务。
5、再次运行 regedt32,浏览至 HKEY_LOCAL_MACHINE oftware/Microsoft/MSDTC,然后删除 TurnOffRpcSecurity 项。
但是实际上该方法基本上解决不了问题,经过长时间的反复实践,我终于按下面的方法解决了:
(方法二)
1、按照方法一的方法处理一遍,如果不行,再继续下面的方法
2、安装windows 2003 sp1,安装好后,方法一中的第4步设置对话框和原来不一样了,选择“事务管理通讯”中的“不要求验证”
3、最好安装好MDAC2.8
3、通过查找,在C:找到名为“hosts”的文件(没有扩展名),通常路径为C:/WINDOWS/system32/drivers/etc,将对方服务器的IP和计算机对应起来,参考如下:
========================================
# Copyright (c) 1993-1999 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
# www.knowsky.com
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
127.0.0.1 localhost
192.168.1.2 中心
192.168.1.3 西站
192.168.106.35 信息中心2
=============================================
一定要将每台服务器的hosts文件都修改好
通过以上办法,我的分布式就可以正常运行了,速度也非常快
 
多人接受答案了。
 
后退
顶部