Dapper + MSAccess:如何获取插入行的标识符

Dapper + MSAccess: How to get identifier of inserted row

我在 C# 中使用 Dapper,后端是 MS Access。我的 DAL 方法在数据库中插入记录。我想 return 插入行的唯一标识符(或更新的具有唯一标识符的 POCO)。 我期待我的功能如下(我知道这不起作用;只是为了解释我想要什么):-

public MyPoco Insert(MyPoco myPoco)
{
    sql = @"INSERT INTO MyTable (Field1, Field2) VALUES (@Field1, @Field2)";
    var param = GetMappedParams(myPoco);//ID property here is null.
    var result = _connection.Query<MyPoco>(sql, param, null, false, null, CommandType.Text);.Single();
    return result;//This result now contains ID that is created by database.
}

我来自 NHibernate 世界,POCO 使用 NH 自动更新。如果不;我们可以调用 Refresh 方法并更新 ID。 我不知道如何使用 Dapper 实现此目的。

我阅读了关于 SO 的 this 问题,该问题与 SQL 服务器无关。

另一个 this 问题没有已接受的答案。

我阅读了 this 问题,其中接受的答案解释了使用 @@Identity 的陷阱。

这对我有用:

static MyPoco Insert(MyPoco myPoco)
{
    string sql = "INSERT INTO MyTable (Field1, Field2) VALUES (@Field1, @Field2)";
    _connection.Execute(sql, new {myPoco.Field1, myPoco.Field2});
    myPoco.ID = _connection.Query<int>("SELECT @@IDENTITY").Single();
    return myPoco;  // This result now contains ID that is created by database.
}

请注意,这将适用于 Access 数据库的 OleDbConnection,但它不适用于 OdbcConnection

编辑回复:评论

为了确保连接在 INSERT 和 SELECT 调用之间保持打开状态,我们可以这样做:

static void Insert(MyPoco myPoco)
{
    string sql = "INSERT INTO MyTable (Field1, Field2) VALUES (@Field1, @Field2)";
    bool connAlreadyOpen = (_connection.State == System.Data.ConnectionState.Open);
    if (!connAlreadyOpen)
    {
        _connection.Open();
    }
    _connection.Execute(sql, new {myPoco.Field1, myPoco.Field2});
    myPoco.ID = _connection.Query<int>("SELECT @@IDENTITY").Single();
    if (!connAlreadyOpen)
    {
        _connection.Close();
    }
    return;  // (myPoco now contains ID that is created by database.)
}

只是一些额外的想法:如果 @@Identity pitfalls 是一个问题,那么另一种选择是提前在代码中创建一个新的 GUID,然后将该 GUID 与其余数据一起插入,而不是而不是让 Access 在创建新记录时创建标识值。

我很欣赏只有当您的特定情况允许 table 的 GUID 主键时才有效,但它确实保证您知道您刚刚插入的记录的键的真实值。

或者,如果您不想要 GUID 键,您可以创建一个 table,单行保存应用程序中任何手动管理键的当前种子值。然后,您可以在每次要插入新记录时手动增加特定种子的值。与 GUID 方法一样,您随后将手动插入带有记录的 ID,这次 ID 将是您刚刚检索到的新递增的种子。

同样,这应该保证每个插入都有一个唯一的键,尽管现在您正在为每个插入执行一次读取和两次写入。