mysql

时间:2015-06-08 13:20:22

标签: c# mysql

我有一个POS系统,用于在两个不同的位置创建收据。我现在遇到的问题是,当两个位置同时输入收据时,他们会有相同的收据ID,因此,我做了一个非常糟糕的方法来解决这个问题。

while (!success)
{
    try
    {
        MySqlCommand myCommand4 = new MySqlCommand("Insert into OrderRecords_table values('" + OrderID + "','" + customerCode + "','" + customer + "','" + TelComboBox.Text + "','" + LicenseComboBox.Text + "','" +
              DriverComboBox.Text + "','" + AddressComboBox.Text + "','" + LocationTypeComboBox.Text + "','" + PickupComboBox.Text + "','" + CustomerTypeLabel.Text + "','" +
           Convert.ToDecimal(TotalPriceLabel.Text) + "','" + status + "','" + note + "','" + sandReceiptNo + "','" + createtiming + "','" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "')", myConnection52);
        myCommand4.ExecuteNonQuery();
        if (retried == true)
        {
            MessageBox.Show("收據號碼已改為: " + OrderID);
        }
        success = true;
    }
    catch (MySqlException ex)
    {
        switch (ex.Number)
        {
            case 1062:
                retried = true;
                OrderID = OrderID.Substring(0, 1) + (Convert.ToInt32(OrderID.Substring(1, OrderID.Length - 1)) + 1).ToString("00000");
                success = false;
                break;
        }
    }
}

我写了这个以捕获异常,并在重复键发生时增加收据号,并且当我第一次测试时它工作正常,但是,它不会再捕获异常了,它只会插入记录。

我不知道它是如何打破mysql的规则的。 现在的情况如下: 如果我有收据编号的记录:m00001(orderID col) 而另一个程序试图插入一个也是m00001的收据号,它应该捕获该异常,但它以某种方式插入两个m00001。 (orderID列设置为主键)。

我正在网上做一些研究,看看有没有其他方法来解决这个问题,我发现了这个

  

INSERT INTO表(a,b,c)VALUES(1,2,3)     ON DUPLICATE KEY UPDATE c = c + 1;

然而,这更新旧记录而不是新记录,是否有另一种方法可以更新我试图插入的记录如果发现重复?

谢谢

2 个答案:

答案 0 :(得分:1)

经典并发控制问题。现代关系数据库通过让数据库生成ID来处理这个问题。在内部,数据库使用mutex来确保只有一个线程能够立即递增计数器。这通常通过序列或包含该功能的特殊数据类型在SQL中公开。在MySQL中,有一种称为SERIAL的特殊数据类型,它将使用MySQL的内部序列生成器AUTO_INCREMENT自动处理ID。

否则,您必须自己实现锁定和并发控制。我不建议这样做,因为MySQL可以比你更好,更快地完成它,但它是可能的。

更改现有列以开始使用AUTO_INCREMENT是一项简单的操作,可以针对较小的数据集(少于一百万行左右)快速完成。我们假设你有一张如下表:

mysql> SHOW CREATE TABLE t_receipts;
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                            |
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_receipts | CREATE TABLE `t_receipts` (
  `id` bigint(20) unsigned NOT NULL,
  `amount` double(8,2) DEFAULT NULL,
  `date_created` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

转换表格非常简单:

ALTER TABLE t_receipts CHANGE id id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT;

或者,使用SERIAL快捷方式:

ALTER TABLE t_receipts CHANGE id id SERIAL;

答案 1 :(得分:0)

visual studio有一个很棒的工具叫做.net的实体框架,有一个guide to use it with MySQL。它会让一切变得更安全,更容易,建议你使用它。

如果出现问题,使用实体框架和Linq,如重复键,它将始终抛出异常。如果由于异常而无法使用自动增量或GUID,则创建密钥会更容易,您将始终知道您尝试插入的密钥何时出错。

数据库中的表只是C#中的一个具有实体模型的类,您只需在该字段中创建此类填充的新对象,将其添加到集合(对应于数据库中的记录)和保存。在保存时,它将检查它是否是原始的并且将创建记录。

据我所知,无论有多少连接以及如何同时添加记录,这都不会允许重复密钥。

将linq添加到实体模型的示例代码:

MyDbEntities mydb = new MyDbEntities();
Order order = new Order();
order.OrderID = "m0000001";
try
{
    mydb.Order.Add(order);
    mydb.SaveChange();
}
catch (Exception exception)
{
    if(excpetion == duplicate key) // pseudo code, don't know the error for duplicate keys
    {
        order.OrderID = m0000002;
    }
}