如何仅发送一次 SQL 查询并使用 Worker 服务保护重复项
How to send SQL query only once and protect for duplicates with Worker service
我在 windows Worker 服务 中创建了一个服务,它定期连接到数据库并将 table 中的第一个最新行发送到API
但是如何让服务只发送一次同一行并等到下一个新行出现。
ID
不能有相同的值,是否可以创建条件dbResult[0]
(id)已经发送的行!=
dbResult[0]
可以发送?
我的部分代码:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
string connectionString = "User=SYSDBA;" +
"Password=masterkey;" +
"Database=test.DTB;" +
"DataSource=localhost;" +
"Port:3050";
FbConnection mConnection = new FbConnection(connectionString);
mConnection.Open();
FbTransaction mTransaction = mConnection.BeginTransaction();
string SQLCommandText = "select first 1 * from TABLE where NAME = 449 order by DATE desc ";
FbCommand mCommand = new FbCommand(SQLCommandText, mConnection, mTransaction);
FbDataReader mReader = mCommand.ExecuteReader();
if (mReader.Read())
{
var values = new object[mReader.FieldCount];
{
mReader.GetValues(values);
var dbResult = values.Distinct().ToArray();
var dbResults = (string.Join("|", dbResult));
var result = new
{
ID = dbResult[0],
NAME = dbResult[1],
DATE = dbResult[2],
};
var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
}
}
}
catch (Exception ex)
{
Log.Fatal(ex, "Problem reading the database.");
}
await Task.Delay(10000, stoppingToken);
}
}
}
从 Barr J
得到很好的线索后更新
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
string connectionString = "User=SYSDBA;" +
"Password=masterkey;" +
"Database=test.DTB;" +
"DataSource=localhost;" +
"Port:3050";
FbConnection mConnection = new FbConnection(connectionString);
mConnection.Open();
FbTransaction mTransaction = mConnection.BeginTransaction();
string SQLCommandText = "select NAME, DATE from TABLE where NAME = 449 and ISSENT = 0";
FbCommand mCommand = new FbCommand(SQLCommandText, mConnection, mTransaction);
FbDataReader mReader = mCommand.ExecuteReader();
while (mReader.Read())
{
var values = new object[mReader.FieldCount];
{
mReader.GetValues(values);
var dbResult = values.Distinct().ToArray();
var dbResults = (string.Join("|", dbResult));
var result = new
{
ID = dbResult[0],
NAME = dbResult[1],
DATE = dbResult[2],
};
var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
using FbConnection UpdateConnection = new(connectionString);
UpdateConnection.Open();
FbCommand writeCommand = new("update TABLE set ISSENT = @isSentValue where ID= @idValue", UpdateConnection);
writeCommand.Parameters.Add("@isSentValue", 1);
writeCommand.Parameters.Add("@idValue", dbResult[0]);
writeCommand.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Log.Fatal(ex, "Problem reading the database.");
}
await Task.Delay(10000, stoppingToken);
}
}
}
因为您使用的是 worker 和 运行 异步操作,我不建议混合使用会使本已繁琐的调试过程复杂化的条件。
我会在您的 table 中添加一个列,并将其用作名为 IsSent
的标志列
然后您的查询将如下所示:
select...... where name = X and IsSent = Y ...."
这样您将只获得未发送的行。
您可以通过其他方式查询代码中的行并检查 ID 是否已发送。
更干净、更好、更轻松。
使您的代码易于维护。
我建议通过缓存新数据在您的辅助服务上实施 MemCache 或简单的内存缓存。整个或只是键标识符字段值。然后,您可以在下次查询 Db 时传递该值,其中 Id > CachedId 或 Id != CachedId order by desc.
在任何时候,当您检索数据时,您都会 it/upsert 使用该 ID 缓存您的缓存。
这些examples/references供您参考
https://qawithexperts.com/article/c-sharp/in-memory-cache-c-explanation-with-example/302
我在 windows Worker 服务 中创建了一个服务,它定期连接到数据库并将 table 中的第一个最新行发送到API
但是如何让服务只发送一次同一行并等到下一个新行出现。
ID
不能有相同的值,是否可以创建条件dbResult[0]
(id)已经发送的行!=
dbResult[0]
可以发送?
我的部分代码:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
string connectionString = "User=SYSDBA;" +
"Password=masterkey;" +
"Database=test.DTB;" +
"DataSource=localhost;" +
"Port:3050";
FbConnection mConnection = new FbConnection(connectionString);
mConnection.Open();
FbTransaction mTransaction = mConnection.BeginTransaction();
string SQLCommandText = "select first 1 * from TABLE where NAME = 449 order by DATE desc ";
FbCommand mCommand = new FbCommand(SQLCommandText, mConnection, mTransaction);
FbDataReader mReader = mCommand.ExecuteReader();
if (mReader.Read())
{
var values = new object[mReader.FieldCount];
{
mReader.GetValues(values);
var dbResult = values.Distinct().ToArray();
var dbResults = (string.Join("|", dbResult));
var result = new
{
ID = dbResult[0],
NAME = dbResult[1],
DATE = dbResult[2],
};
var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
}
}
}
catch (Exception ex)
{
Log.Fatal(ex, "Problem reading the database.");
}
await Task.Delay(10000, stoppingToken);
}
}
}
从 Barr J
得到很好的线索后更新protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
string connectionString = "User=SYSDBA;" +
"Password=masterkey;" +
"Database=test.DTB;" +
"DataSource=localhost;" +
"Port:3050";
FbConnection mConnection = new FbConnection(connectionString);
mConnection.Open();
FbTransaction mTransaction = mConnection.BeginTransaction();
string SQLCommandText = "select NAME, DATE from TABLE where NAME = 449 and ISSENT = 0";
FbCommand mCommand = new FbCommand(SQLCommandText, mConnection, mTransaction);
FbDataReader mReader = mCommand.ExecuteReader();
while (mReader.Read())
{
var values = new object[mReader.FieldCount];
{
mReader.GetValues(values);
var dbResult = values.Distinct().ToArray();
var dbResults = (string.Join("|", dbResult));
var result = new
{
ID = dbResult[0],
NAME = dbResult[1],
DATE = dbResult[2],
};
var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
using FbConnection UpdateConnection = new(connectionString);
UpdateConnection.Open();
FbCommand writeCommand = new("update TABLE set ISSENT = @isSentValue where ID= @idValue", UpdateConnection);
writeCommand.Parameters.Add("@isSentValue", 1);
writeCommand.Parameters.Add("@idValue", dbResult[0]);
writeCommand.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Log.Fatal(ex, "Problem reading the database.");
}
await Task.Delay(10000, stoppingToken);
}
}
}
因为您使用的是 worker 和 运行 异步操作,我不建议混合使用会使本已繁琐的调试过程复杂化的条件。
我会在您的 table 中添加一个列,并将其用作名为 IsSent
然后您的查询将如下所示:
select...... where name = X and IsSent = Y ...."
这样您将只获得未发送的行。 您可以通过其他方式查询代码中的行并检查 ID 是否已发送。
更干净、更好、更轻松。
使您的代码易于维护。
我建议通过缓存新数据在您的辅助服务上实施 MemCache 或简单的内存缓存。整个或只是键标识符字段值。然后,您可以在下次查询 Db 时传递该值,其中 Id > CachedId 或 Id != CachedId order by desc.
在任何时候,当您检索数据时,您都会 it/upsert 使用该 ID 缓存您的缓存。
这些examples/references供您参考
https://qawithexperts.com/article/c-sharp/in-memory-cache-c-explanation-with-example/302