为什么这个查询会产生文件共享冲突?
本文关键字:文件共享 冲突 查询 为什么 | 更新日期: 2023-09-27 18:07:26
下面的代码给了我这个错误(我从catch块中的MessageBox.Show()
中得到它)
" PopulateBla()中的异常:存在文件共享违规。一个不同的进程可能正在使用文件[,,,,,,]
using (SqlCeCommand cmd = new SqlCeCommand(SQL_GET_VENDOR_ITEMS, new SqlCeConnection(SQLCE_CONN_STR)))
{
cmd.Parameters.Add("@VendorID", SqlDbType.NVarChar, 10).Value = vendorId;
cmd.Parameters.Add("@VendorItemID", SqlDbType.NVarChar, 19).Value = vendorItemId;
try
{
cmd.Connection.Open();
using (SqlCeDataReader SQLCEReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
if (SQLCEReader.Read())
{
itemID = SQLCEReader.GetString(ITEMID_INDEX);
packSize = SQLCEReader.GetString(PACKSIZE_INDEX);
recordFound = true;
}
}
}
catch (SqlCeException err)
{
MessageBox.Show(string.Format("Exception in PopulateControlsIfVendorItemsFound: {0}'r'n", err.Message));//TODO: Remove
}
finally
{
if (cmd.Connection.State == ConnectionState.Open)
{
cmd.Connection.Close();
}
}
}
SQL_GET_VENDOR_ITEMS
是我的查询字符串。
这里可能发生什么文件共享问题?
更新这种代码使得下面的攻击所推荐的重构变得困难:
public void setINVQueryItemGroup( string ID )
{
try
{
dynSQL += " INNER JOIN td_item_group ON t_inv.id = td_item_group.id AND t_inv.pack_size = td_item_group.pack_size WHERE td_item_group.item_group_id = '" + ID + "'";
}
catch( Exception ex )
{
CCR.ExceptionHandler( ex, "InvFile.setINVQueryDept" );
}
}
一个SQL语句被附加到一个单独的方法,改变一个全局变量(dynSQL),同时可能允许SQL注入(取决于在哪里/如何分配ID)。如果这还不够,抛出的任何异常都可能误导疲惫的猎人,因为它表明它发生在不同的方法中(无疑是粗心的复制-粘贴操作的受害者)。
这是"编码恐怖"的价值。在短短的几行代码中,您可以忽略多少最佳实践?
下面是另一个例子:
string dynSQL = "SELECT * FROM purgatory WHERE vendor_item = '" + VendorItem + "' ";
if (vendor_id != "")
{
dynSQL += "AND vendor_id = '" + vendor_id + "' ";
}
可以通过将参数替换为"? ",但是决定要分配哪些/多少个参数的代码将比Joe Garagiola的平均代码丑42倍。
我非常喜欢Chris使用单一连接到数据库的想法。你可以像这样将它声明为你的类的全局变量:
public ClayShannonDatabaseClass
{
private SqlCeConnection m_openConnection;
public ClayShannonDatabaseClass()
{
m_openConnection = new SqlCeConnection();
m_openConnection.Open();
}
public void Dispose()
{
m_openConnection.Close();
m_openConnection.Dispose();
m_openConnection = null;
}
}
当你试图打开数据库时,我猜你的代码会崩溃。
为了验证这一点,您可以在代码中插入一个整数值来帮助您调试。
的例子:
int debugStep = 0;
try
{
//cmd.Connection.Open(); (don't call this if you use m_openConnection)
debugStep = 1;
using (SqlCeDataReader SQLCEReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
debugStep = 2;
if (SQLCEReader.Read())
{
debugStep = 3;
itemID = SQLCEReader.GetString(ITEMID_INDEX);
debugStep = 4;
packSize = SQLCEReader.GetString(PACKSIZE_INDEX);
debugStep = 5;
recordFound = true;
}
}
}
catch (SqlCeException err)
{
string msg = string.Format("Exception in PopulateControlsIfVendorItemsFound: {0}'r'n", err.Message);
string ttl = string.Format("Debug Step: {0}", debugStep);
MessageBox.Show(msg, ttl); //TODO: Remove
}
// finally (don't call this if you use m_openConnection)
// {
// if (cmd.Connection.State == ConnectionState.Open)
// {
// cmd.Connection.Close();
// }
// }
我猜你的错误在第一步
如果文件没有被标记为只读(您检查了这一点,对吗?),那么您就有另一个对该文件具有非共享锁的进程。
SQL CE附带的isql.exe数据库浏览器如果在后台运行是一个常见的罪魁祸首。
根据你的SQLCE版本,很有可能另一个进程有一个打开的连接(不记得哪个版本开始允许多个进程连接),所以如果你在后台有任何其他应用程序打开了它,这可能也是一个问题。
你还使用了一船到那个数据库的连接,它们并不总是被清理并立即释放Dispose。我强烈建议构建一个简单的连接管理器类,它保持一个(或更像两个)到数据库的连接,并且只在所有操作中重用它们。