使用Sub-sonic ActiveRecord以原子方式维护计数器

时间:2010-05-12 05:25:37

标签: subsonic subsonic3 subsonic-active-record

我正在尝试找出在一个表中以原子方式递增计数器的正确方法,并将该递增的值用作另一个记录中的伪显示ID。

我拥有的是公司表和工作表。我希望每家公司都拥有自己的job_numbers。我有一个自动增量job_id,但这些数字在所有公司共享。即:每个公司的工作编号通常应该没有间隙地增加。

即:

  • 公司(company_id,next_job_number)
  • jobs(company_id,job_id,job_number)

目前我正在这样做(作为部分工作类的方法):

public void SaveJob()
{
    using (var scope = new System.Transactions.TransactionScope())
    {
        if (job_id == 0)
        {
            _db.Update<company>()
                .SetExpression("next_job_number").EqualTo("next_job_number+1")
                .Where<company>(x => x.company_id == company_id)
                .Execute();

            company c = _db.companies.SingleOrDefault(x => x.company_id == company_id);

            job_number = c.next_job_number;
        }

        // Save the job
        this.Save();

        scope.Complete();
    }
}

它似乎有用,但我不确定这里是否有陷阱?这只是感觉不对,但我不确定如何做到这一点。

任何建议表示赞赏。

2 个答案:

答案 0 :(得分:1)

首先,

您应该将TransactionScope与SharedDbConnectionScope结合使用,否则您的交易将无法按预期运行。

其次,

我会使用另一种方法使用单个语句,而无需将job_id保存到公司中)

  1. 使用job_number = 0保存记录

  2. 使用类似的内容更新记录

    UPDATE JOBS SET JOB_NUMBER =     (SELECT MAX(job_number)+1 FROM JOBS WHERE company_id = 12345)     WHERE job_id =“+ this.job_id;

  3. (你只需要将此查询转换为亚音速语法,我不使用subsonic3) 这应该保证每个公司的作业号都是唯一的(如果你在事务中包装save和update命令并使用表锁)。

答案 1 :(得分:1)

在高容量多用户系统上使用动态代码获取当前最高值可能存在风险(潜在的重复值)。

另一种方法可能是创建一个包含两列的新表;一个字符PK,另一个整数来存储相关的最后一个值。每次需要新值时,请增加相关公司记录中的值,并将该值用于订单号。角色PK包括:

"LAST_ORDER_NUMBER_COMPANY_" + company_id

我有一个存储过程来调用,它会在公司第一次订购时自动启动新记录,或者为后续订单增加新记录,然后返回新的订单号值。