【问题标题】:SqlConnection via Remoting通过远程处理的 SqlConnection
【发布时间】:2014-04-03 15:31:32
【问题描述】:

我开发了一个带有插件的 wpf 主机应用程序并希望共享它们 SqlConnection,但是当我尝试通过 Remoting 传递 SqlConnection 的对象时,我得到一个错误:

remoting cannot find field 'objectid' on type 'system.data.sqlclient.sqlconnection'

Google 和 SO 没有帮助我,我发现的唯一主题是链接断开 :(

我能以某种方式通过 SqlConnection 吗?问题是我已经有了基于 ado.net 的应用程序,我没有可能重写它们。另一方面,我需要为不同的插件提供对同一连接的访问​​权限,因为它们可以通过临时表进行互操作。

异常信息:

(last error: Remoting cannot find field 'ObjectID' on type 'System.Data.SqlClient.SqlConnection'.). 
StackTrace:
Server stack trace: 
   at System.Object.GetFieldInfo(String typeName, String fieldName)
   at System.Object.FieldGetter(String typeName, String fieldName, Object& val)
   at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at System.Object.FieldGetter(String typeName, String fieldName, Object& val)
   at System.Data.SqlClient.SqlCommand.set_Connection(SqlConnection value)
   at LSSample.SampleUserControl.ExecuteSqlLocal() in c:\Users\voskresenskiy\Documents\Visual Studio 2013\Projects\UIContainer\WpfHost\LSSample\SampleUserControl.xaml.cs:line

如果有任何帮助,我将不胜感激

【问题讨论】:

  • 您真的需要相同的连接还是仅仅连接到相同的数据库
  • @DStanley 是的,我需要相同的连接,因为我需要访问临时表。此外,任务是最小化与数据库的连接(它会过多地加载我们的数据库)

标签: c# .net ado.net remoting


【解决方案1】:

从异常调用堆栈和使用反射器我可以看到SqlCommand.set_Connection 正在尝试访问SqlConnection.ObjectIDSqlConnection.ObjectID 被标记为内部,只有公共成员可以通过远程访问。

SqlConnection 不使用池来最小化数据库连接数吗? SQL Server Connection Pooling

您是否可以有一个进程与数据库对话,然后所有其他进程都将从它请求数据,只需将查询字符串传递给它?

【讨论】:

  • 是的,你是对的,但问题是我的插件在不同的进程中运行,这就是我使用远程处理的原因。好吧,msdn 告诉我,SqlConnection 继承了 MarshalByRefObject。
  • @AlexVoskresenskiy 你是对的。你能从你的异常中添加完整的堆栈跟踪吗?
  • 抱歉回答晚了,我已经为问题添加了更多信息
  • 尼尔,我可以用它做点什么,还是我必须投降? :)
  • @AlexVoskresenskiy 我对 ADO.NET 不太熟悉,所以我不知道是否有一种方法可以在没有 SqlCommand 的情况下获取数据?但是你可能会在某个时候遇到类似的问题。更改您的设计可能会更好,也许就像我在回答中建议的那样。
【解决方案2】:

我们最近遇到了同样的问题,我认为问题是通过调用它的构造函数在本地创建 SqlCommand。然后将连接分配给它时,它也会尝试在本地克隆连接,但由于某些内部属性无法通过远程处理而失败。

对我们有用的解决方法是像这样在连接上调用CreateCommand()

void MethodRunningInAppDomainB(SqlConnection connectionFromAppDomainA, SqlTransaction transactionFromAppDomainA)
{
    using (var cmd = connectionFromAppDomainA.CreateCommand())
    {
        cmd.CommandText = "this is my query";
        cmd.Transaction = transaction;

        cmd.Parameters.Add(...);
        ...

        cmd.ExecuteNonQuery();
    }
}

基本上,连接和事务来自主应用程序,该应用程序被传递给在不同 AppDomain 中运行的插件(因此可以卸载),该插件可以在主查询的上下文中执行一些自定义命令。

我的怀疑是,在连接上调用 CreateCommand() 会远程调用回调并在连接所在的同一应用程序域中创建命令,而您返回的创建命令可能是它的代理,这就是为什么采用这种方式有效。

不确定我对问题的解释是否 100% 正确,但对我来说听起来有点合乎逻辑,无论如何它为我们解决了问题。

【讨论】:

  • 嗯,很高兴听到我的主题很有用。您的方法的主要问题是 SQLConnection 提供了更多的可能性,而不仅仅是 SQLCommand,即传递 DataReader/DataWriter 也将成为噩梦。但是,当然,如果您只能处理命令,那么该解决方案看起来很棒。
猜你喜欢
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多