使用yield return实现数据库队列

时间:2013-06-28 22:57:03

标签: c# .net sql-server-2008 queue yield-return

我正在重构遗留应用程序。有问题的应用程序使用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);
            }
        }
    } 
}

0 个答案:

没有答案