我遇到了一个问题''不属于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);
}
}
如果有人帮助我解决此问题,请提前感谢您。
答案 0 :(得分:0)
如果线程之间共享dt
,则必须同步对其的访问权限,可能使用Monitor
或lock
。
如果不共享,请尝试为每个使用三个不同的DataTable
。
您的代码段和说明不足以显示完整的方案。
答案 1 :(得分:0)
我已经通过在几周内付出了很多努力来解决这个问题,并在这里找到了SqlDataAdapter的详细文档http://msdn.microsoft.com/en-us/library/ms810286.aspx,它是如何工作的,但不知何故,SqlDataAdapter的行为与本地DataTable变量与成员或实例变量一样,它们永远不应该是相同的,因为这两种类型的变量都有自己独立的内存空间,永远不会被覆盖。我还向MS发布了一个错误但到目前为止没有得到任何答案。
此问题有两种解决方法。
1-每当您想要管理并发和多线程时,必须为SqlDataAdapter定义DataTableMappings和DataColumnMappings。
2-为每次调用使用SqlDataReader和单独的连接