如何解决如何在带有 ms access 数据库的 c# windows 窗体中添加条件语句?
我正在使用连接到 Microsoft Access 数据库的 c# windows 窗体应用程序。如果 txtSupplyLeft 小于 5,我希望 txtOrderMore 文本框显示“yes”,如果 txtSupplyLeft 大于 5,则显示“no”。我希望在将新记录插入数据库后发生这种情况。这是我想出来的
private void btnSave_Click(object sender,EventArgs e)
{
try
{
connection.open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = "insert into Products (ProductName,ProductPrice,Quantity,[Weight(g)],DaysSupplyLeft) values ('"+txtProductName.Text+"',"+txtProductPrice.Text+ "," + txtQuantity.Text + "," + txtWeight.Text + "," + txtSupplyLeft.Text + ")";
command.ExecuteNonQuery();
txtProductName.Text = "";
txtProductPrice.Text = "";
txtQuantity.Text = "";
txtWeight.Text = "";
txtSupplyLeft.Text = "";
MessageBox.Show("Data saved");
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error" + ex);
}
try
{
connection.open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = "insert into Products ([OrderMore?]) values ('Yes') where "+txtSupplyLeft.Text+"<5";
command.ExecuteNonQuery();
txtOrderMore.Text = "Yes";
MessageBox.Show("Data saved");
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error" + ex);
}
try
{
connection.open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = "insert into Products ([OrderMore?]) values ('No') where "+txtSupplyLeft.Text+"";
command.ExecuteNonQuery();
txtOrderMore.Text = "No";
connection.Close();
}
catch(Exception ex)
{
MessageBox.Show("Error" + ex);
}
}
但是每当我运行此代码时,输出“是”的条件不起作用,也就是说,当我输入低于 5 的值时,我永远不会得到“是”。它确实输出“否”,但是每当我保存新记录时,我获取连接异常,当我在每个 try 循环的末尾明确添加“connection.Close()”时,它告诉我连接尚未关闭。 我对 Windows 窗体和 sql 查询非常陌生,因此我不确定我可能出错的地方。 在推荐参数化查询之前,我已经看到很多评论,但我不太确定该怎么做。
解决方法
在 OleDbCommand 中使用参数时,了解以下内容很重要:
OLE DB .NET Provider 不支持命名参数传递 SQL 语句或被调用的存储过程的参数 当 CommandType 设置为 Text 时,OleDbCommand。在这种情况下, 必须使用问号 (?) 占位符。例如:
SELECT * FROM Customers WHERE CustomerID = ?
因此,OleDbParameter 对象添加到 OleDbParameterCollection 必须直接对应的位置 命令文本中参数的问号占位符。
下面,我将展示如何向 Access 数据库中插入数据,以及如何更新 Access 数据库中的数据。我将在整个代码中使用 OleDbParameter
。
访问数据库名称:Database1.accdb
在Access(设计视图)中,
表格名称:产品
- ID:自动编号
- 产品名称:短文本(常规选项卡 => 字段大小:50)
- 价格:货币(常规标签 => 格式:货币)
- 数量:数量
- 重量(g):数量
- DaysSupplyLeft:数量
- ReorderWhenQuantityReaches:数量
- OrderMore:是/否(常规选项卡 => 格式:是/否)
如果以编程方式创建表,请使用以下列定义:
表格名称:产品
- ID:AutoIncrement 非空主键
- 产品名称:varchar(50) 不为空
- 价格:货币
- 数量:整数
- 重量(g):整数
- DaysSupplyLeft:整数
- ReorderWhenQuantityReaches:整数
- OrderMore:位
注意:以编程方式创建表后,要使其在 Access 中看起来如所需,可能需要更改某些字段(列)的“格式”属性。在 Access 中打开数据库。右键单击“产品”。选择“设计视图”。然后按照上述“In Access(设计视图)”中的说明设置属性。
在您的 VS 项目中,确保您的项目具有 System.Data
的引用。
VS 2019:
- 在 VS 菜单中,点击项目
- 选择添加参考
- 点击装配
- 检查系统数据
创建一个名为HelperAccess
的类- 在 VS 菜单中,点击项目
- 选择添加类...(名称:HelperAccess.cs)
在 HelperAccess.cs 中添加以下 using 语句:
using System.Data.OleDb;
在“HelperAccess.cs”中添加以下变量:
private string _databaseFilename = string.Empty;
private string _connectionString = string.Empty;
然后添加以下构造函数:
public HelperAccess(string databaseFilename)
{
_databaseFilename = databaseFilename;
_connectionString = String.Format("Provider = Microsoft.ACE.OLEDB.12.0; Data Source = {0};Persist Security Info=False;",_databaseFilename);
}
在“HelperAccess.cs”中,创建一个名为AddProduct的方法,添加一个返回变量,并添加return语句
public int AddProduct(string productName,decimal price,int quantity,double weightInGrams,int daysSupplyLeft,int reorderWhenQuantityReaches,bool orderMore = false)
{
int result = 0;
return result;
}
我们将从创建 SQL 开始,这样我们就知道需要指定哪些参数。
string sqlText = "INSERT INTO Product (ProductName,Price,Quantity,[Weight(g)],DaysSupplyLeft,ReorderWhenQuantityReaches,OrderMore) VALUES(?,?,?)";
接下来,我们将创建 OleDbConnection
的实例并打开连接。使用 using
语句时,可确保在执行超出范围时关闭和/或释放对象。
public int AddProduct(string productName,bool orderMore = false)
{
int result = 0;
string sqlText = "INSERT INTO Product (ProductName,?)";
using (OleDbConnection con = new OleDbConnection(_connectionString))
{
//open connection
con.Open();
}
return result;
}
现在,我们将在 OleDbCommand
的实例中创建一个 OleDbConnection
的实例。
public int AddProduct(string productName,?)";
using (OleDbConnection con = new OleDbConnection(_connectionString))
{
//open connection
con.Open();
using (OleDbCommand sqlCmd = new OleDbCommand(sqlText,con))
{
}
}
return result;
}
我们来看看如何声明一个参数。首先,创建一个新的 OleDbParameter
实例。
OleDbParameter paramProductName = new OleDbParameter();
现在,设置属性。为数据库列设置正确的数据类型很重要。虽然 OleDbCommand 不使用“ParameterName”,但我选择设置该属性是因为它使调试更容易。如果未设置该值,则该值将显示为“Parameter1”、“Parameter2”等...
根据Set the field size(访问),
- Long Integer — 适用于范围从 -2,147,483,648 到 +2,647 的整数。存储要求为四个字节。
Data types for Access desktop databases
- 货币:货币数据,以 4 位小数精度存储。 8 字节
- Yes/No:布尔(真/假)数据; Access 存储数字 值零 (0) 表示假,-1 表示真。 1 个字节。
并根据Integral numeric types (C# reference)
- int -2,648 到 2,647 有符号 32 位整数 System.Int32
我们还需要查看OleDbType Enum
-
BigInt:一个 64 位有符号整数 (DBTYPE_I8)。这映射到 Int64。
-
Boolean:布尔值
-
货币:货币价值...
-
十进制:
-
Double:浮点数...
-
整数:一个 32 位有符号整数 (DBTYPE_I4)。这映射到 Int32。
OleDbParameter paramProductName = new OleDbParameter(); paramProductName.OleDbType = OleDbType.VarChar; paramProductName.ParameterName = "@productName"; paramProductName.Value = 产品名称;
要将属性添加到我们的 OleDbCommand (sqlCmd) 实例,我们执行以下操作:
sqlCmd.Parameters.Add(paramProductName);
这是我们目前所拥有的:
public int AddProduct(string productName,con))
{
OleDbParameter paramProductName = new OleDbParameter();
paramProductName.OleDbType = OleDbType.VarChar;
paramProductName.ParameterName = "@productName";
paramProductName.Value = productName;
//add parameter
sqlCmd.Parameters.Add(paramProductName);
}
}
return result;
}
现在,我们可以添加其余的参数,记住它们必须按照使用(引用)的顺序添加。在我们做之前,让我们看看如何执行 SQL。
执行 SQL:
result = sqlCmd.ExecuteNonQuery();
添加产品:
public int AddProduct(string productName,con))
{
//ProductName
OleDbParameter paramProductName = new OleDbParameter();
paramProductName.OleDbType = OleDbType.VarChar;
paramProductName.ParameterName = "@productName";
paramProductName.Value = productName;
//add parameter
sqlCmd.Parameters.Add(paramProductName);
//Price
OleDbParameter paramPrice = new OleDbParameter();
paramPrice.OleDbType = OleDbType.Currency;
paramPrice.ParameterName = "@price";
paramPrice.Value = price;
//add parameter
sqlCmd.Parameters.Add(paramPrice);
//Quantity
OleDbParameter paramQuantity = new OleDbParameter();
paramQuantity.OleDbType = OleDbType.Integer;
paramQuantity.ParameterName = "@quantity";
paramQuantity.Value = quantity;
//add parameter
sqlCmd.Parameters.Add(paramQuantity);
//Weight(g)
OleDbParameter paramWeight = new OleDbParameter();
paramWeight.OleDbType = OleDbType.Double;
paramWeight.ParameterName = "@weight";
paramWeight.Value = weightInGrams;
//add parameter
sqlCmd.Parameters.Add(paramWeight);
//DaysSupplyLeft
OleDbParameter paramDaysSupplyLeft = new OleDbParameter();
paramDaysSupplyLeft.OleDbType = OleDbType.Integer;
paramDaysSupplyLeft.ParameterName = "@daysSupplyLeft";
paramDaysSupplyLeft.Value = daysSupplyLeft;
//add parameter
sqlCmd.Parameters.Add(paramDaysSupplyLeft);
//ReorderWhenSupplyReaches
OleDbParameter paramReorderWhenQuantityReaches = new OleDbParameter();
paramReorderWhenQuantityReaches.OleDbType = OleDbType.Integer;
paramReorderWhenQuantityReaches.ParameterName = "@reorderWhenQuantityReaches";
paramReorderWhenQuantityReaches.Value = reorderWhenQuantityReaches;
//add parameter
sqlCmd.Parameters.Add(paramReorderWhenQuantityReaches);
//orderMore
OleDbParameter paramOrderMore = new OleDbParameter();
paramOrderMore.OleDbType = OleDbType.Boolean;
paramOrderMore.ParameterName = "@orderMore";
paramOrderMore.Value = orderMore;
//add parameter
sqlCmd.Parameters.Add(paramOrderMore);
//execute command
result = sqlCmd.ExecuteNonQuery();
}
}
return result;
}
现在让我们看看如何更新数据库表。在“HelperAccess.cs”
中创建一个名为 UpdateProductQuantity 的方法public int UpdateProductQuantity(int id,int quantity)
{
}
创建 SQL:
string sqlText = "UPDATE Product SET Quantity = ? WHERE ID = ?";
其余的代码与前面的方法类似,不再赘述。
更新产品数量:
public int UpdateProductQuantity(int id,int quantity)
{
string sqlText = "UPDATE Product SET Quantity = ? WHERE ID = ?";
int result = 0;
using (OleDbConnection con = new OleDbConnection(_connectionString))
{
//open connection
con.Open();
using (OleDbCommand sqlCmd = new OleDbCommand(sqlText,con))
{
//Note: Parameters MUST be added in the order that they are used (referenced) since
//ParameterName isn't used by OleDbCommand. However,setting the
//ParameterName property can be useful for debugging
// Quantity
OleDbParameter paramQuantity = new OleDbParameter();
paramQuantity.OleDbType = OleDbType.Integer;
paramQuantity.ParameterName = "@quantity";
//calculate quantity remaining and set value
paramQuantity.Value = quantity;
//add parameter
sqlCmd.Parameters.Add(paramQuantity);
//ID
OleDbParameter paramId = new OleDbParameter();
paramId.OleDbType = OleDbType.Integer;
paramId.ParameterName = "@id";
paramId.Value = id;
//add parameter
sqlCmd.Parameters.Add(paramId);
//execute command
result = sqlCmd.ExecuteNonQuery();
}
}
return result;
}
我们如何才能使用代码来更新数量?如果客户进行了购买,我们将要更新数量。可以获取当前数量,减去购买的数量,并更新数据库。然后,如果数量低于 Product 表中“ReorderWhenQuantityReaches”中指定的数量,我们将“OrderMore”的值设置为“Yes”并引发订阅者可以侦听的事件。这可用于更新表单上的 OrderMore TextBox。
让我们创建一个方法来从 Product 表中获取现有数量。由于这是更新过程的一部分,我们可以打开连接一次,然后在我们获取数量的方法中使用该连接。
在“HelperAccess.cs”中,创建一个名为GetCurrentQuantity的方法,添加一个返回变量,并添加返回语句。
public int GetCurrentQuantity(OleDbConnection con,int id)
{
int currentQuantity = 0;
return currentQuantity;
}
创建 SQL 查询:
string sqlText = "SELECT quantity from Product where ID = ?";
创建一个OleDbCommand实例,并添加id参数:
public int GetCurrentQuantity(OleDbConnection con,int id)
{
int currentQuantity = 0;
string sqlText = "SELECT quantity from Product where ID = ?";
using (OleDbCommand sqlCmd = new OleDbCommand(sqlText,con))
{
//ID
OleDbParameter paramId = new OleDbParameter();
paramId.OleDbType = OleDbType.Integer;
paramId.ParameterName = "@id";
paramId.Value = id;
//add parameter
sqlCmd.Parameters.Add(paramId);
}
return currentQuantity;
}
有多种方法可以从数据库中读取值。我们将使用 OleDbDataReader。创建一个新的 OleDbReader 实例并使用它来获取值。该列可以通过它的列名或查询中的相对位置来引用。该指数从零开始。由于我们只指定了一列,所以索引为零。
获取当前数量:
public int GetCurrentQuantity(OleDbConnection con,con))
{
//ID
OleDbParameter paramId = new OleDbParameter();
paramId.OleDbType = OleDbType.Integer;
paramId.ParameterName = "@id";
paramId.Value = id;
//add parameter
sqlCmd.Parameters.Add(paramId);
//get value
using (OleDbDataReader reader = sqlCmd.ExecuteReader())
{
while (reader.Read())
{
currentQuantity = (int)reader[0];
}
}
}
return currentQuantity;
}
接下来,让我们创建一个方法,当数量发生变化时更新“OrderMore”的值。我们将获得数量的当前值。我们还需要知道什么数量“触发”了要更改的“OrderMore”的值。该值存储在“ReorderWhenQuantityReaches”中,因此我们需要检索该值并将其与数量进行比较。完成比较后,我们可以引发事件 (OrderMoreValueUpdated) 以通知订阅者“OrderMore”的值是“Yes”还是“No”。
在我们继续之前,因为我们将在我们的方法中引发一个事件,让我们看看如何创建一个可以订阅的事件。我不会详细介绍事件,因为人们可以找到许多关于它们的文章/帖子。我将只展示需要添加以使其工作的代码。在“HelperAccess.cs”的顶部添加以下代码:
public class HelperAccess
{
public delegate void EventHandlerOrderMoreValueUpdated(object sender,string e);
//event that subscribers can subscribe to
public event EventHandlerOrderMoreValueUpdated OrderMoreValueUpdated;
...
}
以下是引发事件的方法:
//check if event has subscribers
if (OrderMoreValueUpdated != null)
{
//raise event
OrderMoreValueUpdated(this,"test");
}
现在我们准备好创建我们的方法 UpdateOrderMore。由于我已经介绍了代码的不同部分,我将只展示完整的方法。
更新订单更多
public int UpdateOrderMore(OleDbConnection con,int id)
{
string sqlText = string.Empty;
int reorderWhenQuantityReaches = 0;
int result = 0;
//get Quantity
int currentQuantity = GetCurrentQuantity(con,id);
//get ReorderWhenQuantityReaches
sqlText = "SELECT ReorderWhenQuantityReaches from Product where ID = ?";
using (OleDbCommand sqlCmd = new OleDbCommand(sqlText,con))
{
//ParameterName isn't used by OleDbCommand. However,setting the
//ParameterName property can be useful for debugging
//ID
OleDbParameter paramId = new OleDbParameter();
paramId.OleDbType = OleDbType.Integer;
paramId.ParameterName = "@id";
paramId.Value = id;
//add parameter
sqlCmd.Parameters.Add(paramId);
//get value
using (OleDbDataReader reader = sqlCmd.ExecuteReader())
{
while (reader.Read())
{
reorderWhenQuantityReaches = (int)reader[0];
}
}
}
sqlText = "UPDATE Product SET OrderMore = ? WHERE ID = ?";
using (OleDbCommand sqlCmd = new OleDbCommand(sqlText,con))
{
//Note: Parameters MUST be added in the order that they are used (referenced) since
//ParameterName isn't used by OleDbCommand. However,setting the
//ParameterName property can be useful for debugging
//if quantity is below value specified in ReorderWhenQuantityReaches,then
//set OrderMore to true (Yes)
bool orderMoreVal = false;
string orderMoreValStr = string.Empty;
if (currentQuantity <= reorderWhenQuantityReaches)
{
orderMoreVal = true;
orderMoreValStr = "Yes";
}
else
{
orderMoreVal = false;
orderMoreValStr = "No";
}
//OrderMore
OleDbParameter paramOrderMore = new OleDbParameter();
paramOrderMore.OleDbType = OleDbType.Boolean;
paramOrderMore.ParameterName = "@orderMore";
paramOrderMore.Value = orderMoreVal;
//add parameter
sqlCmd.Parameters.Add(paramOrderMore);
//ID
OleDbParameter paramId = new OleDbParameter();
paramId.OleDbType = OleDbType.Integer;
paramId.ParameterName = "@id";
paramId.Value = id;
//add parameter
sqlCmd.Parameters.Add(paramId);
//execute command
result = sqlCmd.ExecuteNonQuery();
//check if event has subscribers
if (OrderMoreValueUpdated != null)
{
//raise event
OrderMoreValueUpdated(this,orderMoreValStr);
}
}
return result;
}
最后,这里有一个结合了上述代码的方法。作为完成销售的一部分,当前数量需要减去正在购买的数量。然后我们会检查是否需要订购更多产品并报告结果。
UpdateProductQuantityAfterPurchase
public int UpdateProductQuantityAfterPurchase(int id,int quantityPurchased)
{
string sqlText = "UPDATE Product SET Quantity = ? WHERE ID = ?";
int resultUpdateQuantity = 0;
using (OleDbConnection con = new OleDbConnection(_connectionString))
{
//open connection
con.Open();
//get current quantity
int currentQuantity = GetCurrentQuantity(con,id);
using (OleDbCommand sqlCmd = new OleDbCommand(sqlText,setting the
//ParameterName property can be useful for debugging
// Quantity
OleDbParameter paramQuantity = new OleDbParameter();
paramQuantity.OleDbType = OleDbType.Integer;
paramQuantity.ParameterName = "@quantity";
//calculate quantity remaining and set value
paramQuantity.Value = currentQuantity - quantityPurchased;
//add parameter
sqlCmd.Parameters.Add(paramQuantity);
//ID
OleDbParameter paramId = new OleDbParameter();
paramId.OleDbType = OleDbType.Integer;
paramId.ParameterName = "@id";
paramId.Value = id;
//add parameter
sqlCmd.Parameters.Add(paramId);
//execute command
resultUpdateQuantity = sqlCmd.ExecuteNonQuery();
if (resultUpdateQuantity > 0)
{
System.Diagnostics.Debug.WriteLine("Info: " + resultUpdateQuantity + " row updated.");
}
}
//update OrderMore
int resultUpdateOrderMore = UpdateOrderMore(con,id);
}
return resultUpdateQuantity;
}
由于帖子的字符限制,我无法在“Helper.cs”中添加方法的所有代码,但代码在上面。 “Helper.cs”的布局应类似于以下内容(“...”是代码所在的位置):
HelperAccess.cs
public class HelperAccess
{
private string _databaseFilename = string.Empty;
private string _connectionString = string.Empty;
public delegate void EventHandlerOrderMoreValueUpdated(object sender,string e);
//event that subscribers can subscribe to
public event EventHandlerOrderMoreValueUpdated OrderMoreValueUpdated;
public HelperAccess(string databaseFilename)
{
_databaseFilename = databaseFilename;
_connectionString = String.Format("Provider = Microsoft.ACE.OLEDB.12.0; Data Source = {0};Persist Security Info=False;",_databaseFilename);
}
public int AddProduct(string productName,bool orderMore = false)
{
...
}
public int GetCurrentQuantity(OleDbConnection con,int id)
{
...
}
public int UpdateProductQuantity(int id,int quantity)
{
...
}
public int UpdateProductQuantityAfterPurchase(int id,int quantityPurchased)
{
...
}
public int UpdateOrderMore(OleDbConnection con,int id)
{
...
}
}
使用
为了测试,我在 Form1 中添加了以下内容:
以下 TextBox 控件已添加到 Form1:
- 名称:textBoxId
- 名称:textBoxProductName
- 名称:textBoxPrice
- 名称:textBoxQuantity
- 名称:textBoxWeight
- 名称:textBoxReorderWhenQuantityReaches
- 名称:textBoxDaysSupplyLeft
- 名称:textBoxOrderMore(只读:true)
注意:我还在每个 TextBox 的左侧添加了一个标签。
最后,我在 Form1.cs 中添加了一个按钮(名称:btnSave)
Form1.cs:
public partial class Form1 : Form
{
private static string _databaseFilename = @"C:\Users\Test\Documents\Database1.accdb";
private HelperAccess _helperAccess = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender,EventArgs e)
{
//create new instance
_helperAccess = new HelperAccess(_databaseFilename);
//subscribe to event
_helperAccess.OrderMoreValueUpdated += _helperAccess_OrderMoreValueUpdated;
}
private void _helperAccess_OrderMoreValueUpdated(object sender,string e)
{
//needed for cross-threaded operations
if (textBoxOrderMore.InvokeRequired)
{
textBoxOrderMore.Invoke((MethodInvoker) delegate
{
textBoxOrderMore.Text = (string)e;
textBoxOrderMore.Refresh();
});
}
else
{
textBoxOrderMore.Text = (string)e;
textBoxOrderMore.Refresh();
}
}
private void AddProduct()
{
//convert price
decimal price = 0;
Decimal.TryParse(textBoxPrice.Text,out price);
//convert quantity
int quantity = 0;
Int32.TryParse(textBoxQuantity.Text,out quantity);
//convert weight
double weight = 0;
Double.TryParse(textBoxWeight.Text,out weight);
//convert days supply left
int daysSupplyLeft = 0;
Int32.TryParse(textBoxDaysSupplyLeft.Text,out daysSupplyLeft);
//convert reorder when quantity reaches
int reorderWhenQuantityReaches = 0;
Int32.TryParse(textBoxReorderWhenQuantityReaches.Text,out reorderWhenQuantityReaches);
//add product to database
int result = _helperAccess.AddProduct(textBoxProductName.Text,price,quantity,weight,daysSupplyLeft,reorderWhenQuantityReaches);
}
private void btnSave_Click(object sender,EventArgs e)
{
AddProduct();
}
}
要使用 UpdateProductQuantityAfterPurchase:
_helperAccess.UpdateProductQuantityAfterPurchase(id,1);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。