紧接着执行SELECT,然后在Access中通过.NET进行UPDATE

时间:2015-10-01 14:59:42

标签: .net ms-access

我的问题相对简单,但我还没有找到答案。我有一个只包含一行的表。该行有两列,ClientCode和ClientIndex。

我有一个选择查询,如下所示:

SELECT i.ClientCode + FORMAT(i.ClientIndex, "000000") FROM Indexes as I;

现在我运行了选择后我想将ClientIndex增加一个。

UPDATE Indexes SET ClientIndex = ClientIndex + 1;

动机:我希望能够创建连续的报告编号。因此,每次生成报告时,我都希望ClientIndex递增。为此,我需要锁定表格,选择我的号码,增加索引并解锁表格。

这在MS Access 2013中是否可行?使用存储过程在Sql中是微不足道的;但要求声明Access,并没有办法解决这个问题。此外,我正在构建一个客户端应用程序(使用.NET和F#),它将检索报告编号。

编辑:看起来人们并没有真正得到这个问题。我希望两个语句SELECTUPDATE在同一个执行中运行。我 NOT 想要从某个客户端调用select并更新。

普通旧t-sql中的SP看起来像是:

CREATE PROCEDURE something
AS
BEGIN
    declare @result as nchar(10);
    set @result = <<select query>>;
    <<update query>>;
    select @result;
END

编辑:我正在构建一个.NET F#应用程序,它将调用Access数据库并检索报告编号。此应用程序将在Windows服务器上的Windows服务中运行。此报告编号可以大间隔同时调用约100次。

1 个答案:

答案 0 :(得分:3)

  

我不希望调用代码必须对数据库进行两次调用才能使其正常工作。换句话说,我希望SELECT语句和UPDATE语句在同一个执行中运行。

Access数据库引擎不支持多语句批处理,因此您无法执行...

SELECT i.ClientCode + FORMAT(i.ClientIndex, "000000") FROM Indexes as I;
UPDATE Indexes SET ClientIndex = ClientIndex + 1;

......一气呵成。每个SQL语句都必须单独执行。

现在,如果在隔离级别为“可序列化”的事务中执行这两个语句,则不会出现问题。遗憾的是,Access ODBC Driver和Access OLEDB Provider都不支持System.Data.IsolationLevel.Serializable进行事务处理。它们支持的最高隔离级别是ReadCommitted,这并不足以阻止两个进程获得相同的ClientIndex。

据我所知,模仿可序列化事务的唯一方法是使用具有悲观锁定的Access DAO,如下所示:

// COM Reference required:
// Microsoft Office 14.0 Access Database Engine Object Library
//
var dbe = new DBEngine();
Database db = dbe.OpenDatabase(@"\\DINSDALE\Public\test\locktestBE.accdb");
Recordset rst = db.OpenRecordset("SELECT ClientIndex FROM Indexes",
        RecordsetTypeEnum.dbOpenDynaset,
        RecordsetOptionEnum.dbFailOnError,
        LockTypeEnum.dbPessimistic);
bool keepTrying = true;
while (keepTrying)
{
    try
    {
        rst.Edit();
        int nextId = rst.Fields["ClientIndex"].Value;  // get next ID,
        rst.Fields["ClientIndex"].Value = nextId + 1;  // increment value, and
        rst.Update();                                  // write it back
        rst.Close();
        Console.WriteLine("The assigned ID is {0}", nextId);
        keepTrying = false;
    }
    catch (System.Runtime.InteropServices.COMException e)
    {
        if (!e.Message.StartsWith("Could not update; currently locked by user"))
        {
            throw;
        }
    }
}
db.Close();

但是,在继续使用Access数据库作为服务的数据存储之前,您应该仔细考虑。处理高并发性和执行粒度锁定并不适合Access数据库引擎。 (Microsoft“强烈建议不要在Web应用程序中使用Access”有几个原因 - 参考:here - 听起来很多原因也适用于您的应用程序。)