[英]C# How to have an object available in another method?
我有兩種方法,在ConnecttoDB方法中,我創建了一個名為connection的對象,但是在第二種方法中我需要該對象來指定SQLiteCommand。 我如何擁有該對象在InsertField方法中可用?
public class Database
{
private static string _datasource;
private static string _table;
private static string _field;
private static string _values;
public static void ConnecttoDB(string datasource)
{
_datasource = datasource;
SQLiteConnection connection = new SQLiteConnection();
connection.ConnectionString = "Data Source: " + _datasource;
connection.Open();
}
public static void InsertField(string table, string field, string values)
{
SQLiteCommand command = new SQLiteCommand(/*connection*/);
_table = table;
_field = field;
_values = values;
String.Format("INSERT INTO {0} {1} VALUES{2}", _table, _field, _values);
}
}
你的班級設計很奇怪。 為什么沒有明顯的原因_values
_table
, _field
和_values
聲明為類字段,卻不為connection
這樣做,這將解決您的問題? 您可以直接使用table
, field
和values
參數,而無需事先將它們分配給字段。
讓我建議另一種方法:
public class Database
{
private string _connectionString;
// Pass the datasource through the constructor.
public Database(string datasource)
{
_connectionString = "Data Source: " + datasource;
}
public void InsertField(string table, string field, object value)
{
using (var conn = new SQLiteConnection(_connectionString)) {
string sql = String.Format("INSERT INTO {0} ({1}) VALUES (@1)",
table, field);
var command = new SQLiteCommand(sql, conn);
command.Parameters.AddWithValue("@1", value);
conn.Open();
command.ExecuteNonQuery();
}
}
}
(未經測試,SQLite的調用約定可能有所不同)
我正在使用與任何類型兼容的value
的object
類型。 我也將此值作為命令參數傳遞給命令。 這樣,例如, DateTime
值將自動轉換為SQLite的正確格式。 它還可以防止SQL注入 。 (我希望表名和字段名由應用程序定義,而不是由用戶輸入。)
由於存在連接池,系統會保持連接打開一段時間,並自動重用打開的連接。 因此, connection.Open();
每次調用時,call並不會真正從物理上重新打開連接。 另一方面,這種方法可防止連接打開很長時間並且不使用系統資源。
using
語句自動負責關閉連接並處置連接所使用的資源-即使在代碼塊到達其末尾之前發生異常時也是如此。
您可以像這樣使用它:
var db = new Database("my data source");
db.InsertField("myTable", "myField", 100);
更新
如果您需要可變數量的參數,則可以將數組用於字段和值:
public void InsertField(string table, string[] fields, object[] values)
{
if (fields.Length != values.Length) {
throw new ArgumentException(
"The fields and values arrays must have the same length");
}
string fieldNames = String.Join(", ", fields); // ==> "name1, name2, name3"
// ==> "@p0, @p1, @p2"
string paramNames = String.Join(", ",
Enumerable.Range(0, fields.Length)
.Select(i => "@p" + i)
.ToArray()
);
using (var conn = new SQLiteConnection(_connectionString)) {
string sql = String.Format("INSERT INTO {0} ({1}) VALUES ({2})",
table, fieldNames, paramNames);
var command = new SQLiteCommand(sql, conn);
for (int i = 0; i < values.Length; i++) {
command.Parameters.AddWithValue("@p" + i, values[i]);
}
conn.Open();
command.ExecuteNonQuery();
}
}
用法:
var db = new Database("my data source");
db.InsertField("myTable",
new string[]{ "Name", "Quantity", "Price", "Date" },
new object[]{ "Apples", 12, 2.65m, DateTime.Now });
要解決您當前面臨的問題:
在這種情況下,您實際上不應該這樣做。 您的兩種方法應該是一種方法:
public static void InsertField(string table, string field, string values)
{
using (SQLiteConnection connection = new SQLiteConnection())
{
using (SQLiteCommand command = new SQLiteCommand(connection))
{
_table = table;
_field = field;
_values = values;
String.Format("INSERT INTO {0} {1} VALUES{2}", _table, _field, _values);
// and the rest of the code, incomplete in the example
}
}
}
建立一個SQL連接對象並不是一個昂貴的過程。 而且只有一行代碼。 因此,通過將其卸載到另一種方法實際上並沒有節省太多。 但是,您正在做的事情是引入了許多其他潛在的運行時問題(與您當前遇到的容易看到的編譯時問題相對),例如資源泄漏和已處置對象錯誤。
將連接和命令對象封裝得盡可能接近其用法,並在完成處理后盡快處理它們。 對基礎系統進行了很好的優化,可以在您再次需要使用另一種方法(或再次調用相同的方法)時重新創建它們。
要從字面上解決您的問題:
考慮從一個方法傳遞給另一方法的變量的范圍,方法的范圍等。您可以選擇。
變量是方法所在的對象的屬性嗎? 例如,在一個Person
對象中,您可能有一個稱為Height
東西。 既然描述了這個人,那么它可以是類級別的:
public int Height { get; private set; }
public void OneMethod(int someValue)
{
// more code
Height = someValue;
// more code
}
public void AnotherMethod()
{
// more code
someOtherObject.DoSomethingWithHeight(Height);
// more code
}
如果該值實際上未描述對象,而是在較小的范圍內,請考慮將其傳遞給方法。 也許像:
public void SomeMethod()
{
// more code
var someValue = 123;
// more code
AHelperMethod(someValue);
// more code
}
private void AHelperMethod(int aValue)
{
// more code
someOtherObject.DoSomethingWithValue(aValue);
// more code
}
在第一種情況下,這兩種方法都是使用描述該對象的屬性對對象本身執行某些操作。 在第二種情況下,第二種方法只是對象內部的某種東西,僅用於支持第一種方法的高級操作。 在第一種方法中,它可能只是內聯代碼,但出於重用,可讀性,保持抽象級別或許多重構原因,它已被提取到其自己的方法中。
將連接作為私有實例字段使用,然后可以在所有方法中使用它。 同時刪除靜態關鍵字。 很少使用靜態,並且通常很糟糕。
public class Database
{
private string _datasource;
private string _table;
private string _field;
private string _values;
private SQLiteConnection _connection;
public void ConnecttoDB(string datasource)
{
_datasource = datasource;
_connection = new SQLiteConnection();
_connection.ConnectionString = "Data Source: " + _datasource;
_connection.Open();
}
public void InsertField(string table, string field, string values)
{
SQLiteCommand command = new SQLiteCommand(_connection);
_table = table;
_field = field;
_values = values;
String.Format("INSERT INTO {0} {1} VALUES{2}", _table, _field, _values);
}
}
您可以全局保留它,也可以將其作為參數傳遞給InsertFields。 在后一種情況下,您必須在某個地方創建它,然后將其傳遞給Your方法。
最簡單的方法是將SQLiteConnection對象聲明為類級變量。 然后,您的InsertField方法將使用類級別變量,如下所示:
SQLiteCommand命令=新的SQLiteCommand(連接);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.