Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用yield-return实现数据库队列_C#_.net_Sql Server 2008_Queue_Yield Return - Fatal编程技术网

C# 使用yield-return实现数据库队列

C# 使用yield-return实现数据库队列,c#,.net,sql-server-2008,queue,yield-return,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 (

我正在重构一个遗留应用程序。该应用程序使用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);
            }
        }
    } 
}
//数据库DDL
如果对象id(“作业”)不为空,则开始
删除表格作业;
结束
去
创建表作业
(
Id int标识(1,1)不为空主键
,JobStatus varchar(50)不为空
);
插入作业
选择“等待”
联合所有
选择“等待”
联合所有
选择“处理”
联合所有
选择“已完成”
联合所有
选择“失败”;
//单元测试
//数据模型
公开密封班工作
{
公共只读int-JobId;
公共作业(int jobId)
{
JobId=JobId;
}
}
[测试夹具]
公营职业培训
{
私有常量字符串连接字符串=
“数据源=;初始目录=;集成安全性=True;连接超时=15;加密=False;TrustServerCertificate=False”;
常量字符串SQL=
@“声明@jobId表(jobId int)
更新前(1)个作业
设置作业状态='正在处理'
将.Id输出插入@jobId
其中JobStatus=‘Waiting’
从@JobId;“;中选择JobId;
[测试]
公共职位空缺()
{
foreach(作业中的var作业)
{
Assert.NotNull(作业,“作业为空”);
Console.WriteLine(job.JobId);
}
}
公共静态可数作业
{
得到
{
while(true)
{
Job=null;
做
{
使用(var连接=新的SqlConnection(connectionString))
{
使用(var命令=新的SqlCommand(SQL,连接))
{
connection.Open();
var reader=command.ExecuteReader();
if(reader.Read())
{
job=新作业(将.ToInt32(读卡器[“JobId”]);
收益回报工作;
}
}
}
}while(job==null);
任务延迟(1000);
}
}
} 
}

Task.Delay的调用在那里没有任何作用。调用本身只是启动一个任务,该任务将在一秒钟内完成;它不会在一秒钟内阻塞线程,你需要
线程。为此,睡眠
。当你
产生
你的下一个
作业时,你就完成了给定的命令/连接,但在请求下一个之前,你不会真正处理它们。这意味着您在调用方处理给定项的整个时间内都在保留这些资源。您可以通过将
屈服
移动到
do
/
的末尾之后,而
,轻松解决此问题。请注意,这不会影响程序的正确性,只是有助于更有效地利用系统资源。@RedPolygon老实说,我不知道它在那里做什么。也许它只是为了调试的目的而存在,以代表真正的工作,我不知道。在任何情况下,这都是一个无用的操作,可能应该删除。代码复查问题->移动。此问题似乎与主题无关,因为它是代码复查