2013-02-25 37 views
2

我有一个带有标识列的表。
使用厚重,这样的代码使用大规模插入我试图获得scope_identity时得到DBNull()

var table = new Categories(); 
var newID = table.Insert(new {CategoryName = "Buck Fify Stuff", Description = "Things I like"}); 

然后

table.Scalar("select scope_identity()"); 

返回DBNull :(

什么我需要做的不同,以获得实际插入的标识值

+2

你得到NEWID的table.insert语句后什么样的价值?基于应该是识别值的文档。 – JeffO 2013-02-25 20:44:11

回答

5

的MSDN文档指出SCOPE_IDENTITY

“可检索任何表产生在当前会话中的最后一个标识值”

望着Massive source code,似乎到Scalar()每次调用打开一个新的连接:

/// <summary> 
/// Returns a single result 
/// </summary> 
public virtual object Scalar(string sql, params object[] args) { 
    object result = null; 
    using (var conn = OpenConnection()) {   // <-- see this ... 
     result = CreateCommand(sql, conn, args).ExecuteScalar(); 
    } 
    return result; 
} 

... 

/// <summary> 
/// Returns and OpenConnection 
/// </summary> 
public virtual DbConnection OpenConnection() { 
    var result = _factory.CreateConnection(); 
    result.ConnectionString = ConnectionString; 
    result.Open();         // <-- ...and this 
    return result; 
} 

因此,每次你做table.Scalar("select scope_identity()");你实际上是在一个新的连接(这意味着一个不同的会话/范围)这样做。

这解释了DBNull的结果。

但既然你已经这样做:

var newID = table.Insert(...) 

你可能想在插入之后发生,检查的newID价值;我希望你会在那里找到好的东西。

至少,这是什么Insert()代码使我相信:

public virtual dynamic Insert(object o) { 
     var ex = o.ToExpando(); 
     if (!IsValid(ex)) { 
      throw new InvalidOperationException("Can't insert: " + String.Join("; ", Errors.ToArray())); 
     } 
     if (BeforeSave(ex)) { 
      using (dynamic conn = OpenConnection()) { 
       var cmd = CreateInsertCommand(ex); 
       cmd.Connection = conn; 
       cmd.ExecuteNonQuery(); 
       cmd.CommandText = "SELECT @@IDENTITY as newID"; 
       ex.ID = cmd.ExecuteScalar(); 
       Inserted(ex); 
      } 
      return ex; 
     } else { 
      return null; 
     } 
    } 
+0

没错。在你的例子中'newID.ID'将具有标识值。谢谢!!! – 2013-02-25 20:48:58