DataTable正在被WCF Web服务.Net 4.0中的另一个DataTable覆盖

时间:2014-09-16 15:16:19

标签: c# .net wcf ado.net

我遇到了一个问题''不属于WCF Web服务中的表。这是因为另一个线程与其他模式覆盖了数据表。我已经通过实现日志进行了调试,发现整个模式和数据已经被另一个数据库调用更改了,这个数据库调用是按顺序在第一个之后调用的。对于我来说,当第一个数据表对象的内存实例未被声明为静态时,第一个数据表对象的内存实例将被第二个数据表对象覆盖。我使用了线程锁定,但遗憾的是它不起作用。我不确定这是MS错误,但可能有一个我目前还不知道的解决方案。

以下是方法调用的顺序: 首先,我使用用户凭据填充数据表以进行用户身份验证,此数据表只有三列和一行。 其次,我用另一个处理请求所需的其他数据填充另一个数据表,然后我再填充一个表来处理请求。

有时,第一个数据表上会弹出错误''不属于表格,有时它出现在第二个数据表中。当我记录表模式时,第二个完全改变了。

以下是第一个数据表的代码:

public UserCredentials GetUserCredentials(string userName)
     {   
        try
        {
            UserCredentials userCredentials = null;

            using (SqlCommand cmd = new SqlCommand())
            {
                    DataTable dt = new DataTable("User");
                    cmd.CommandText = "dbo.[stored procedure]";
                    cmd.Connection = this.connection;
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@UserName", userName);

                    using (SqlDataAdapter sda = new SqlDataAdapter())
                    {
                        sda.SelectCommand = cmd;
                        sda.Fill(dt);
                    }

                    if (dt != null && dt.Rows.Count > 0)
                    {
                        userCredentials = new UserCredentials();
                        userCredentials.UserName = userName;
                        userCredentials.SiteID = dt.Rows[0]["SiteID"].ToString();
                        **userCredentials.Password = dt.Rows[0]["Passphrase"].ToString();**
                    }
                }

            return userCredentials;
        }
        catch (Exception ex)
        {
            throw ex;
        }
     }

第二个数据表:

public GatewayProfile GetGatewayProfile(string siteID)
        {
            Int64 gatewayID = 0;
            string submitterID = "";
            GatewayProfile gatewayProfile = null;

            try
            {
                this.OpenConnection();

                DataTable dtGateway = new DataTable("GTDetails");
                using (SqlCommand cmd = new SqlCommand())
                {
                    cmd.CommandText = "dbo.[stored procedure]";
                    cmd.Connection = this.connection;
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@SiteID", siteID);

                    using (SqlDataAdapter sda = new SqlDataAdapter())
                    {
                        sda.SelectCommand = cmd;
                        sda.Fill(dtGateway);
                    }
                }

                if (dtGateway != null && dtGateway.Rows.Count > 0)
                {
                    gatewayProfile = new GatewayProfile();

                    if (Convert.ToBoolean(dtGateway.Rows[0]["IsDefault"]) == false)
                    {
                        gatewayID = Convert.ToInt64(dtGateway.Rows[0]["GatewayID"]);
                        submitterID = dtGateway.Rows[0]["SubmitterID"].ToString();
                    }

                    DataTable dtRoute = new DataTable("RTDetails");
                    using (SqlCommand cmd = new SqlCommand())
                    {
                        cmd.CommandText = "dbo.[stored procedure]";
                        cmd.Connection = this.connection;
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@GatewayID", gatewayID);
                        cmd.Parameters.AddWithValue("@SubmitterID", submitterID);

                        using (SqlDataAdapter sda = new SqlDataAdapter())
                        {
                            sda.SelectCommand = cmd;
                            sda.Fill(dtRoute);
                        }
                    }

                    if (dtRoute != null && dtRoute.Rows.Count > 0)
                    {
                        gatewayProfile.GatewayID = Convert.ToInt64(dtRoute.Rows[0]["GatewayID"]);
                        gatewayProfile.SubmitterID = dtRoute.Rows[0]["SubmitterID"].ToString().Trim();
                        **gatewayProfile.ReceiverID = dtRoute.Rows[0]["ReceiverID"].ToString().Trim();**
                        gatewayProfile.AuthInfo = ReplaceDBNull(dtRoute.Rows[0]["AuthInfo"], "").Trim();
                        gatewayProfile.SecurityInfo = ReplaceDBNull(dtRoute.Rows[0]["SecurityInfo"], "").Trim();
                    }
                }

                return gatewayProfile;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally 
            {
                this.CloseConnection();
            }
        }

第三个数据表

using (SqlCommand cmd = new SqlCommand())
{
    cmd.CommandText = "dbo.[stored procedure]";
    cmd.Connection = this.connection;
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@param1", param1);
    cmd.Parameters.AddWithValue("@param2", param2);
    cmd.Parameters.AddWithValue("@param3", param3);
    cmd.Parameters.AddWithValue("@param4", param4);

    using (SqlDataAdapter sda = new SqlDataAdapter())
    {
        sda.SelectCommand = cmd;
        sda.Fill(dt);
    }
}

如果有人帮助我解决此问题,请提前感谢您。

2 个答案:

答案 0 :(得分:0)

如果线程之间共享dt,则必须同步对其的访问权限,可能使用Monitorlock

如果不共享,请尝试为每个使用三个不同的DataTable

您的代码段和说明不足以显示完整的方案。

答案 1 :(得分:0)

我已经通过在几周内付出了很多努力来解决这个问题,并在这里找到了SqlDataAdapter的详细文档http://msdn.microsoft.com/en-us/library/ms810286.aspx,它是如何工作的,但不知何故,SqlDataAdapter的行为与本地DataTable变量与成员或实例变量一样,它们永远不应该是相同的,因为这两种类型的变量都有自己独立的内存空间,永远不会被覆盖。我还向MS发布了一个错误但到目前为止没有得到任何答案。

此问题有两种解决方法。

1-每当您想要管理并发和多线程时,必须为SqlDataAdapter定义DataTableMappings和DataColumnMappings。

2-为每次调用使用SqlDataReader和单独的连接