【问题标题】:Database too large to handle? C# or OLEDBCommand数据库太大而无法处理? C# 或 OLEDBCommand
【发布时间】:2016-01-05 15:57:18
【问题描述】:

我创建了一个相当简单的程序来处理年度报告。直到最近它才起作用,但随着 Access 数据库大小的增加,该程序最终停止工作。当我在测试环境中缩小数据库时,它会继续按预期工作。

public List<WorkOrderModel> getAllWorkOrdersForYear(int year)
    {
        List<WorkOrderModel> workOrderList = new List<WorkOrderModel>();
        conn = null;
        //int connectionOpen = openConnection();
        openConnection();
        if (conn.State == ConnectionState.Open)
        {
            result = -1;
            string sql;
            string selectedDate = "04/30/" + (year);
            string endDate = "05/01/" + (year + 1);

            sql = "SELECT * FROM WorkOrder WHERE NOT Completed = 0 AND dateCompleted > #" 
                            + selectedDate + "# AND dateCompleted < #" 
                            + endDate + "# ORDER BY supervisor ASC;";

            // load up and execute sql command
            cmd = new OleDbCommand(sql, conn);
            try
            {
                reader = cmd.ExecuteReader();
            }
            catch (Exception ex)
            {
                // error close the connection
                conn.Close();
                Console.Write("Error - " + ex.Message);
                return workOrderList;
            }

            // successfully got data
            if (reader.HasRows)
            {
                WorkOrderModel wom;
                int num;
                while (reader.Read())
                {
                    //Note: try/catch's for fields with possible null/empty returns
                    num = 0;
                    // create a new workOrderModel object
                    wom = new WorkOrderModel();

                    // load up the object with values
                    wom.setWorkOrderNumber((int)reader.GetValue(num++));
                    wom.setUserID((int)reader.GetValue(num++));
                    wom.setFirstName(reader.GetString(num++));
                    wom.setLastName(reader.GetString(num++));
                    wom.setDateSubmitted(reader.GetDateTime(num++));
                    wom.setCustNum(reader.GetString(num++));
                    wom.setEquipment(reader.GetString(num++));
                    wom.setDescription(reader.GetString(num++));
                    // tech
                    try
                    {
                        wom.setTech(reader.GetString(num++));
                    }
                    catch { wom.setTech(""); }
                    wom.setLabour((double)reader.GetValue(num++));
                    wom.setShopFee((double)reader.GetValue(num++));
                    wom.setHardware((double)reader.GetValue(num++));
                    wom.setElectronicComponets((double)reader.GetValue(num++));
                    wom.setMaterials((double)reader.GetValue(num++));
                    wom.setLabourCost((double)reader.GetDecimal(num++));
                    wom.setSuppliesCost((double)reader.GetDecimal(num++));
                    wom.setTotalCost((double)reader.GetDecimal(num++));
                    // work performed
                    try
                    {
                        wom.setWorkPerformed(reader.GetString(num++));
                    }
                    catch { wom.setWorkPerformed(""); }

                    // date completed
                    try
                    {
                        wom.setDateCompleted(reader.GetDateTime(num++));
                    }
                    catch
                    {
                        DateTime tempDate = DateTime.MinValue;
                        wom.setDateCompleted(tempDate);
                    }
                    // completion flag
                    wom.setIsComplete(reader.GetBoolean(num++));
                    //phone
                    try
                    {
                        wom.setPhone(reader.GetString(num++));
                    }
                    catch { wom.setPhone(""); }

                    //email
                    try
                    {
                        wom.setEmail(reader.GetString(num++));
                    }
                    catch { wom.setEmail(""); }

                    // department
                    try
                    {
                        wom.setDepartment(reader.GetString(num++));
                    }
                    catch { wom.setDepartment(""); }

                    // supervisor
                    try
                    {
                        wom.setSupervisor(reader.GetString(num++));
                    }
                    catch { wom.setSupervisor(""); }
                    // affiliate
                    wom.setAffiliate(reader.GetBoolean(num++));
                    wom.setBilling(reader.GetBoolean(num++));
                    wom.setStatus(reader.GetBoolean(num++));

                    try
                    {
                        wom.setStatusValue(reader.GetString(num++));
                    }
                    catch
                    {
                        wom.setStatusValue("");
                    }

                    try
                    {
                        wom.setBillingFile(reader.GetString(num++));
                    }
                    catch
                    {
                        wom.setBillingFile("");
                    }

                    try
                    {
                        wom.setCommon(reader.GetString(num++));
                    }
                    catch
                    {
                        wom.setCommon("");
                    }
                    try
                    {
                        wom.setSection(reader.GetString(num++));
                    }
                    catch
                    {
                        wom.setSection("");
                    }

                    //cust = wom.getCustNum();

                    // get any extras for each order if the exist
                    sql = "SELECT * FROM Extra WHERE orderID = " + wom.getWorkOrderNumber();
                    OleDbDataReader extrasReader;

                    // are there any extras attached to the work order
                    cmd = new OleDbCommand(sql, conn);
                    try
                    {
                        extrasReader = cmd.ExecuteReader();
                    }
                    catch { extrasReader = null; }

                    // has values
                    if (extrasReader.HasRows)
                    {
                        ExtraModel extra;
                        List<ExtraModel> extList = new List<ExtraModel>();
                        while (extrasReader.Read())
                        {
                            extra = new ExtraModel();
                            extra.setOrderID((int)extrasReader.GetValue(1));
                            extra.setDescription(extrasReader.GetString(2));
                            extra.setPrice((double)extrasReader.GetDecimal(3));
                            extList.Add(extra);
                        }
                        wom.setExtras(extList);
                    }
                    // add object to list
                    workOrderList.Add(wom);
                }
            }// if
            // close connection and return list
            conn.Close();
            return workOrderList;
        }
        else
        {
            workOrderList = null;
            return workOrderList;
        }
    }

【问题讨论】:

  • “停止工作”是对所发生事情的非常模糊的描述。您尝试处理多少行,会发生什么
  • 访问....那是你的问题。它是一个具有严重局限性的个人数据库,并且存在数据库损坏、文件大小增加、多用户支持有限等许多问题。至少转到 SQL Server Express。
  • @AndrewWall 1000 行在这里几乎不是内存问题。但是您没有解决所要求的澄清的第二部分。会发生什么?收到的错误信息是什么?
  • 我建议删除所有那些 try/catch 并使用正确的方法来处理来自 DbReader 的空值: wom.setTech(reader.IsDbNull(num) ? "": reader.GetString (数量)); num++; 如果你有很多空值,你会惊讶于你的代码速度提升
  • 感谢大家的帮助。我过去只学过 Java,这不是我真正的专业领域,因为我只是稍微涉足 C#。再次感谢您!

标签: c# oledbcommand


【解决方案1】:

在您的循环中,您创建另一个 OleDbCommand 和一个阅读器,但您从不关闭它们,这意味着您在数据库上保持一个光标打开。

Close/Dispose 完成后额外的阅读器和命令,或者更好的是使用using 语法。

并且您将cmd 对象重新用于额外的阅读器。不知道是不是错了,反正很丑。

                // are there any extras attached to the work order
                using (var cmdExtras = new OleDbCommand(sql, conn)) 
                using (var extrasReader = cmdExtras.ExecuteReader()) {

                    ExtraModel extra;
                    List<ExtraModel> extList = new List<ExtraModel>();
                    while (extrasReader.Read())
                    {
                        extra = new ExtraModel();
                        extra.setOrderID((int)extrasReader.GetValue(1));
                        extra.setDescription(extrasReader.GetString(2));
                        extra.setPrice((double)extrasReader.GetDecimal(3));
                        extList.Add(extra);
                    }
                    if (extList.Any()) wom.setExtras(extList);
                }

【讨论】:

    【解决方案2】:

    虽然我同意其他人的观点,即替换 Access 应该在该程序的开发路线图上,但根据经验,仅此负载不应导致它失败。

    我们还没有足够的信息来修复它,所以我将采取以下措施来修复它。

    1. 用实际的字段列表替换 SELECT * 查询
    2. 升级 try..catch 块以记录更多信息,包括给定的 InnerExceptions。
    3. 在查询中添加一个 TOP 参数,这样您就可以准确找出导致查询失败的记录数。当您发现您的神奇第一条记录失败时,调整查询以仅返回那条记录。绝对是导致问题的音量,还是个别记录?

    希望这部分内容可以为您指出根本原因并为您解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      • 2014-01-08
      • 2019-11-28
      相关资源
      最近更新 更多