如何仅发送一次 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