編輯!這是錯誤的視頻https://www.youtube.com/watch?v=_mJ3o3ykQrw
在我的資料庫處理程式類中創建了一個名為 AddAttendance 的方法。我可以從其他類訪問它,因為它是靜態的。這是代碼:
public static void AddAttendance(string ID, string DateTime, string Action, string Session)
{
SQLiteConnection sqlite_conn = new SQLiteConnection("Data Source = " database "; Version = 3; New = True; Compress = True;");
try
{
sqlite_conn.Open();
SQLiteCommand sqlite_cmd = sqlite_conn.CreateCommand();
sqlite_cmd.CommandText = "INSERT INTO AttendanceLog (UserID, DateTime, Action, Session) VALUES ("
"'" ID "', '" DateTime "', '" Action "', '" Session "');";
sqlite_cmd.ExecuteNonQuery();
sqlite_conn.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
sqlite_conn.Close();
}
此代碼僅由我系結到按鈕的此對話框表單訪問:
private void buttonAccept_Click(object sender, EventArgs e)
{
if (textBoxID.Text.Length == 0 || textBoxTimeDate.Text.Length == 0)
{
MessageBox.Show("ID or Time and Date cannot be empty!", "Missing field", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (buttonAccept.Text.Equals("Accept"))
{
buttonAccept.Text = "Confirm!";
return;
}
DatabaseHandles.AddAttendance(textBoxID.Text, textBoxTimeDate.Text, comboBoxAction.Text, comboBoxSession.Text);
MessageBox.Show("Record added!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
DialogResult = DialogResult.OK;
}
如果我從我的 Form Kiosk 模式訪問它,它作業得很好,但如果我從其他任何地方訪問它,它報告資料庫被鎖定。
奇怪的是,當我先將它訪問到我的資訊亭模式然后再訪問其他地方時,它作業得很好。
我不知道我錯過了什么。這是我在呼叫表單時使用的相同代碼:
AttendanceInsert ai = new AttendanceInsert();
ai.ShowDialog();
uj5u.com熱心網友回復:
此鎖定問題是由于嘗試重用資料庫連接而引起的。ADO.Net 有一個稱為連接池的功能,因此在整個應用程式中重復使用相同的連接物件是一個非常糟糕的主意,它實際上會使事情變慢,此外還會導致這樣的鎖定問題。
相反,您確實應該為大多數查詢創建一個全新的連接物件,在運行查詢之前立即打開連接,并在查詢完成后立即處理該物件。最簡單的方法是通過一個using塊:
private static string ConnectionString {get;} = "Data Source = " database "; Version = 3; New = True; Compress = True;"
public static void AddAttendance(string ID, string dateTime, string Action, string Session)
{
string sql = "INSERT INTO AttendanceLog (UserID, DateTime, Action, Session) VALUES (@id, @time, @action, @session);";
using (var conn = new SQLiteConnection(ConnectionString))
using (var cmd = new SQLiteCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@id", ID);
// Note the DateTime format. It's necessary to store date values in this way in order to preserve cardinality and allow indexes and date math to function properly.
// Better DB platforms would have a DateTime type to use instead
cmd.Parameters.AddWithValue("@time", DateTime.Parse(dateTime).ToString("yyyy-MM-dd HH:mm:ss"));
cmd.Parameters.AddWithValue("@action", Action);
cmd.Parameters.AddWithValue("@session", session);
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
該using塊將保證連接正確關閉,即使在sqllite_conn.Close()可能錯過呼叫的情況下也是如此。
事情是這樣的:修復這個查詢是不夠的!
您必須修復所有查詢以依賴該using塊,否則您仍有被鎖定的風險。鎖定問題不會顯示在實際導致鎖定的查詢上,而是在資料庫鎖定后運行的查詢上。
在這種情況下,看起來鎖定問題可能發生在您顯示網格的位置。網格查詢運行起來很有趣,不會顯示任何錯誤,但不會釋放其鎖定,因此您在嘗試添加記錄時會遇到錯誤,因為是之后的下一個查詢。
引數也是如此。僅此查詢使用查詢引數而不是字串連接是不夠的。每次在EVERY QUERY中將資料替換為 SQL 字串時,都必須執行此操作。
uj5u.com熱心網友回復:
我不知道它是否能解決你的問題,但沒有理由不做對:
public static void AddAttendance(string id, string datetime, string action, string session)
{
try
{
using (var sqlite_conn = new SQLiteConnection("Data Source = " database "; Version = 3; New = True; Compress = True;")
{
sqlite_conn.Open();
using (var sqlite_cmd = sqlite_conn.CreateCommand())
{
sqlite_cmd.CommandText = "INSERT INTO AttendanceLog (UserID, DateTime, Action, Session) VALUES (@Id, @DateTime, @Action, @Session);";
sqlite_cmd.Parameters.Add(new SqlParameter("@Id", SqlDbType.NVarChar)).Value = id;
sqlite_cmd.Parameters.Add(new SqlParameter("DateTime", SqlDbType.NVarChar)).Value = datetime;
sqlite_cmd.Parameters.Add(new SqlParameter("Action", SqlDbType.NVarChar)).Value = action;
sqlite_cmd.Parameters.Add(new SqlParameter("Session", SqlDbType.NVarChar)).Value = session;
sqlite_cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
這樣,您的連接和 SqlCommand 將被關閉和處理,并且您正在使用引數化查詢,這將防止 SQL 注入。如果您的資料庫列不是 NVarChar,則需要更改它。您還可以為引數定義添加長度。
uj5u.com熱心網友回復:
罪魁禍首是閱讀器,雖然我關閉了與using引數的所有連接,但我忘記關閉我使用的所有閱讀器,我也應該在using這里使用,但你明白了。資料庫被鎖定,讀者未關閉
public static void LoadScannedUser(string ID)
{
string sql = "SELECT * FROM Users WHERE ID = '" ID "'";
using (var conn = new SQLiteConnection(ConnectionString))
{
using (var cmd = conn.CreateCommand())
{
try
{
cmd.CommandText = sql;
conn.Open();
SQLiteDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
scannedUser.ID = reader.GetString(1);
scannedUser.Password = reader.GetString(2);
scannedUser.PPicture = Cryptorizer.Base64ToImage(reader.GetString(3));
scannedUser.FName = reader.GetString(4);
scannedUser.MName = reader.GetString(5);
scannedUser.LName = reader.GetString(6);
scannedUser.Agency = reader.GetString(7);
scannedUser.Position = reader.GetString(8);
}
reader.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/463939.html
