我正在使用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上阅读了this的问题,因为它与SQL Server有关。
另一个this问题尚未接受答案。
我看了this问题,其中接受的答案解释了使用@@Identity
的陷阱。
答案 0 :(得分:3)
这对我有用:
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.)
}
答案 1 :(得分:1)
还有一些额外的想法:如果@@Identity
pitfalls是一个问题,那么另一个选择是在代码中提前创建一个新的GUID,然后将该GUID与其余数据一起插入,而不是让它Access在创建新记录时创建标识值。
我很感激,只有在您的特定情况允许表的GUID主键时,它才会起作用,但它确实保证您知道刚刚插入的记录的键的真值。
或者,如果您不想要GUID键,则可以创建一个包含单行的表,该行包含应用程序中任何手动管理的键的当前种子值。然后,您可以在每次要插入新记录时手动递增特定种子的值。与GUID方法一样,您将手动插入带有记录的ID,这次ID将是您刚刚检索到的新增加的种子。
同样,这应该保证每个插入的唯一键,尽管现在你正在为每个插入执行读取和两次写入。