我正在重构遗留应用程序。有问题的应用程序使用 SQL Server 数据库表对由一个或多个 Windows 服务检索和处理的作业进行排队。我想创建一个迭代器,它在保持正确锁定的同时,拉下一个处于“等待”状态的排队作业进行处理。下面包括一个示例单元测试。我的问题是我的方法是否有任何潜在的阻碍。
// Database DDL
if object_id('Jobs') is not null begin
drop table Jobs;
end
go
create table Jobs
(
Id int identity(1,1) not null primary key clustered
, JobStatus varchar(50) not null
);
insert Jobs
select 'Waiting'
union all
select 'Waiting'
union all
select 'Processing'
union all
select 'Completed'
union all
select 'Failed';
// Unit Test
// Data Model
public sealed class Job
{
public readonly int JobId;
public Job(int jobId)
{
JobId = jobId;
}
}
[TestFixture]
public class JobsTest
{
private const string connectionString =
"Data Source=.;Initial Catalog=<databasename>;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False";
const string SQL =
@"declare @jobId table(JobId int)
update top(1) Jobs
set JobStatus = 'Processing'
output Inserted.Id into @jobId
where JobStatus = 'Waiting'
select JobId from @jobId;";
[Test]
public void CanIterateJobs()
{
foreach (var job in Jobs)
{
Assert.NotNull(job, "job was null.");
Console.WriteLine(job.JobId);
}
}
public static IEnumerable<Job> Jobs
{
get
{
while (true)
{
Job job = null;
do
{
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(SQL, connection))
{
connection.Open();
var reader = command.ExecuteReader();
if (reader.Read())
{
job = new Job(Convert.ToInt32(reader["JobId"]));
yield return job;
}
}
}
} while (job == null);
Task.Delay(1000);
}
}
}
}