从线程中获取数据库中的最新记录

时间:2014-02-14 19:48:21

标签: c# multithreading

我有一个线程,它在数据库中查找最新记录并使用它们进行操作(使用ODBC)。

我遇到的问题是,当我在线程运行时手动将两条记录插入到我的数据库中时,它会返回两条记录,然后返回最后一条记录。

我怎样才能让它只返回那2条记录?

这是我的代码:

public void Run()
{
    // thread alive is set to true, in the main program it is set to false when the user quits
    while (RestTestThread.ThreadAlive)
    {
        System.Threading.Thread.Sleep(1000);   // set to 1000 for quick testing
        try
        {
            // get the data from the database and return to a List<string>
            List<string> postList = Controllers.OdbcController.GetRecords();

            // convert that list into a string
            string post = string.Join(",", postList.ToArray());

            // format that data
            string postData = "{\"Data\":[" + post.TrimEnd(new char[] { ',' }) + "]}";
            Program.postString.Clear();

            // test output
            Console.WriteLine(postData);
         }
         catch (Exception ex)
         {
            Console.WriteLine(ex.Message);
            break;
         }
    }
}

这是Controllers.OdbcController.GetRecords()方法:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Odbc;
using System.Linq;
using System.Text;

namespace WatchItRDBMSService.Controllers
{
   public class OdbcController
   {
       private static string _lastId;
       private static string _dsn;  
       private static string _postData;
       private static OdbcConnection _connection;
       private static OdbcCommand _command;
       private static OdbcDataReader _reader;

       public static List<string> GetRecords()
       {
           List<string> result = new List<string>();
           _dsn = ConfigurationManager.AppSettings["OdbcDsn"];

           if (_dsn != "")
           {
               if (ConfigurationManager.AppSettings["LastId"] == "")
               {
                   // first read, initial, first run of the thread
           // create connection settings
                   string qry = String.Format("SELECT ID, TestValue FROM test.new_table");
                   _connection = new OdbcConnection(_dsn);
                   _connection.Open();
                   _command = _connection.CreateCommand();
                   _command.CommandText = qry;
                   _reader = _command.ExecuteReader();

                   while (_reader.Read())
                   {
                       _postData = String.Empty;
                       _postData += "{";

                       // rows exist (1 or more)
                       for (int i = 0; i < _reader.FieldCount; i++)
                       {
                           if (_postData.Length == 1)
                           {
                               _postData += String.Format("\"{0}\":\"{1}\"", _reader.GetName(i), _reader.GetValue(i));
                           }
                           else
                           {
                               _postData += String.Format(",\"{0}\":\"{1}\"", _reader.GetName(i), _reader.GetValue(i)); 
                           }
                       }
                       _postData += "}";

                       result.Add(_postData);

            // update the latest ID in App.config
                       _lastId = _reader.GetValue(0).ToString();
                       Common.UpdateConfigFile.UpdateAppSetting("LastId", _lastId);
                   }

                   _reader.Close();
                   _command.Dispose();
                   _connection.Close();
               }
               else
               {
                   // successive reads, additions to table will be discovered here
           // set up database connections
                   string qry = String.Format("SELECT ID, TestValue FROM test.new_table WHERE ID > {0} ORDER BY ID DESC", Convert.ToInt32(ConfigurationManager.AppSettings["LastId"]));
                   _connection = new OdbcConnection(_dsn);
                   _connection.Open();
                   _command = _connection.CreateCommand();
                   _command.CommandText = qry;
                   _reader = _command.ExecuteReader();

                   while (_reader.Read())
                   {
                       _postData = String.Empty;
                       _postData += "{";

                       // rows exist (1 or more)
                       for (int i = 0; i < _reader.FieldCount; i++)
                       {
                           if (_postData.Length == 1)
                           {
                               _postData += String.Format("\"{0}\":\"{1}\"", _reader.GetName(i), _reader.GetValue(i));
                           }
                           else
                           {
                               _postData += String.Format(",\"{0}\":\"{1}\"", _reader.GetName(i), _reader.GetValue(i));
                           }
                       }
                       _postData += "}";

                       result.Add(_postData);

              // update the latest ID in App.config
                       _lastId = _reader.GetValue(0).ToString();
                       Common.UpdateConfigFile.UpdateAppSetting("LastId", _lastId);
                   }

                   _reader.Close();
                   _command.Dispose();
                   _connection.Close();
                }
            }
            else
            {
                Console.WriteLine("No Database Connection(s) exist.");
            }
            return result;
        }
    }
}

我的测试表有ID&amp; TestValueID是自动增量)

例如,当我插入2个值时,请说:ID=17 TestValue="Test1", ID=18 TestValue="Test2"

我明白了:

{"Data": [{"ID":18, "TestValue":"Test2"}, {"ID":17, "TestValue":"Test1"}]}
{"Data": [{"ID":18, "TestValue":"Test2"}]}

但我只想要:

{"Data": [{"ID":18, "TestValue":"Test2"}, {"ID":17, "TestValue":"Test1"}]}

2 个答案:

答案 0 :(得分:1)

如果我是你,我会保留数据集中最后一次提取的id

因此,您需要更改Controllers.OdbcController.GetRecords()以接受id并返回最新版本。

使用GetRecords条款id检查where

修改

根据您的更新:您确定ID是否正确传递给配置?

您使用两个不同的调用来保存和检索:

ConfigurationManager.AppSettings["LastId"]

VS

Common.UpdateConfigFile.UpdateAppSetting("LastId", _lastId)

为什么不使用它?

ConfigurationManager.AppSettings["LastId"] = _lastId;

答案 1 :(得分:0)

最好使用C#锁定对象。锁定对象可以防止只有一个线程访问关键区域。

private object lockObj=new object();

public void Run()
{
// thread alive is set to true, in the main program it is set to false when the user quits
while (RestTestThread.ThreadAlive)
{
    System.Threading.Thread.Sleep(1000);   // set to 1000 for quick testing
    try
    {
        lock(lockObj)
       {
           // get the data from the database and return to a List<string>
           List<string> postList = Controllers.OdbcController.GetRecords();

           // convert that list into a string
           string post = string.Join(",", postList.ToArray());

           // format that data
          string postData = "{\"Data\":[" + post.TrimEnd(new char[] { ',' }) + "]}";
          Program.postString.Clear();

          // test output
          Console.WriteLine(postData);
       }
     }
     catch (Exception ex)
     {
        Console.WriteLine(ex.Message);
        break;
     }
}

}