我有一个线程,它在数据库中查找最新记录并使用它们进行操作(使用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; TestValue
(ID
是自动增量)
例如,当我插入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"}]}
答案 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;
}
}
}