我正在使用Dapper和C#,后端是MS Access。我的DAL方法在数据库中插入记录。我想返回插入行的唯一标识符(或带有唯一标识符的更新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上阅读了这个问题,因为它谈到了SQL Server。
另外这个问题不接受的答案。
我读了这个问题,接受的答案解释了使用@@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调用之间的Connection保持打开状态,我们可以这样做:
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
陷阱是一个问题,那么另一个选择是在代码中提前创建一个新的GUID,然后将该GUID与其余数据一起插入,而不是让Access创建身份创建新记录时的值。
我很欣赏只有在您的特定情况允许表的GUID主键时它才会起作用,但它确实保证您知道刚插入的记录的键的真值。
或者,如果您不想要GUID键,则可以创建一个包含单行的表,该行包含应用程序中任何手动管理的键的当前种子值。然后,您可以在每次要插入新记录时手动递增特定种子的值。与GUID方法一样,您随后手动将ID与记录一起插入,这次ID将是您刚刚检索到的新增加的种子。
同样,这应该保证每个插入的唯一键,尽管现在您正在为每个插入执行读取和两次写入。