我正在尝试从 C# Web 表单连接到 MS Access 数据库。
我这样做了:
var parameters = new KeyValuePair<string, object>[]
{
new KeyValuePair<string, object>("@ProjectId", currentInfo.ProjectId),
new KeyValuePair<string, object>("@core", Convert.ToInt16(catalogue.Core.ToString())),
new KeyValuePair<string, object>("@sizee", catalogue.Size)),
new KeyValuePair<string, object>("@applicationId", Convert.ToInt32(applicationComboBox.SelectedValue.ToString()))
};
DataTable typesTable = helper.GetRowsByQuery("FillType",parameters, currentInfo.DBPath);
这是连接数据库的方法:
public DataTable GetRowsByQuery(string queryOrTable, KeyValuePair<string, object>[] parameters, string dbPath)
{
DataTable table = new DataTable();
OleDbDataAdapter adapter = new OleDbDataAdapter();
OleDbConnection connection = new OleDbConnection(GetStringConnection(dbPath));
string sqlCommand = GetSqlCommand(queryOrTable);
OleDbCommand command = new OleDbCommand(sqlCommand, connection);
if (parameters != null)
{
foreach (KeyValuePair<string, object> o in parameters)
{
var parameter = new OleDbParameter(o.Key, o.Value);
SetOleDbTypeAndSize(parameter, o.Value);
command.Parameters.Add(parameter);
}
}
command.CommandText = sqlCommand;
adapter.SelectCommand = command;
try
{
connection.Open();
if (table == null)
{
table = new DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
adapter.FillSchema(table, SchemaType.Source);
}
adapter.Fill(table);
}
finally
{
if (connection.State == ConnectionState.Open)
{
connection.Close();
}
}
return table;
}
查询命令是这样的
SELECT DISTINCT Catalogue.Type
FROM (CableProperty
INNER JOIN Catalogue ON CableProperty.CatalogueId = Catalogue.Id)
WHERE (Catalogue.Core = @core)
AND (Catalogue.[Size] = '@sizee')
AND (CableProperty.ProjectId = @projectId)
AND (CableProperty.CableApplicationId = @applicationId)
查询直接返回 MS Access 数据库本身的结果,但在我的 C# 应用程序中不返回任何结果....
如果我删除
Catalogue
上的内连接条件:
(Catalogue.Core = @core) AND (Catalogue.[Size] = '@sizee')
它也会在应用程序中返回结果。
如评论中所述,不要用引号将参数引起来。
而且,真的不需要尝试创建自己的参数列表(密钥对),因为 ADO.NET SQL 命令对象已经为您提供了这样一个预先构建的集合。
请记住,使用 MS-Access 数据引擎时,参数的顺序很重要,并且必须与它们在查询中出现的顺序匹配。
所以,这个:
string sSQL =
@"SELECT DISTINCT Catalogue.Type
FROM (CableProperty
INNER JOIN Catalogue ON CableProperty.CatalogueId = Catalogue.Id)
WHERE (Catalogue.Core = @core)
AND (Catalogue.[Size] = @sizee)
AND (CableProperty.ProjectId = @projectId)
AND (CableProperty.CableApplicationId = @applicationId)";
OleDbCommand cmdSQL = new OleDbCommand(sSQL);
cmdSQL.Parameters.Add("@core", OleDbType.Integer).Value = 123;
cmdSQL.Parameters.Add("@sizee", OleDbType.VarWChar).Value = "big";
cmdSQL.Parameters.Add("@projectId", OleDbType.Integer).Value = 789;
cmdSQL.Parameters.Add("@applicationId", OleDbType.Integer).Value = 5555;
DataTable CatItems = General.MyRstP(cmdSQL);
那么,想要一个可以在整个应用程序中使用的易于使用的“通用”例程吗?
我建议这个公共静态例程:
public static DataTable MyRstP(OleDbCommand cmd)
{
DataTable rstData = new DataTable();
using (OleDbConnection conn = new OleDbConnection(GetConStr()))
{
using (cmd)
{
cmd.Connection = conn;
try
{
conn.Open();
rstData.Load(cmd.ExecuteReader());
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
}
return rstData;
}
请注意,您甚至可以使用“?”对于 SQL 中的参数,因为正如我所指出的,在 Access 的情况下,参数名称实际上并不重要,重要的是参数添加的顺序。
因此,我认为尝试创建自己的密钥对没有什么价值,因为如上所述,ADO.NET SQL 命令对象已经具有这样的内置集合,更重要的是,您可以使用 OleDbType 强强制转换(自动)输入适合您的参数类型。
另请注意例程如何将连接对象包装在 using 语句中,强烈建议这样做以正确处理与数据库的连接。