2013-01-09 26 views
20

Cố gắng tìm ra cách tốt nhất để sử dụng ExecuteScalar hoặc ExecuteNonQuery nếu tôi muốn trả về cột nhận dạng của hàng mới được chèn. Tôi đã đọc số this question và tôi hiểu sự khác biệt ở đó, nhưng khi nhìn qua một số mã tôi đã viết cách đây vài tuần (trong khi vay nặng từ trang này), tôi thấy rằng trong chèn của tôi, tôi đã sử dụng ExecuteScalar, như vậy:ExecuteScalar vs ExecuteNonQuery khi trả về một giá trị nhận dạng

public static int SaveTest(Test newTest) 
{ 
    var conn = DbConnect.Connection(); 
    const string sqlString = "INSERT INTO dbo.Tests (Tester , Premise) " + 
          "    VALUES (@tester , @premise) " + 
          "SET @newId = SCOPE_IDENTITY(); "; 
    using (conn) 
    { 
     using (var cmd = new SqlCommand(sqlString, conn)) 
     { 
      cmd.Parameters.AddWithValue("@tester", newTest.tester); 
      cmd.Parameters.AddWithValue("@premise", newTest.premise); 
      cmd.Parameters.Add("@newId", SqlDbType.Int).Direction = ParameterDirection.Output; 

      cmd.CommandType = CommandType.Text; 
      conn.Open(); 
      cmd.ExecuteScalar(); 

      return (int) cmd.Parameters["@newId"].Value; 
     } 
    } 
} 

này hoạt động tốt cho những gì tôi cần, vì vậy tôi tự hỏi

  1. cho dù tôi có nên sử dụng ExecuteNonQuery ở đây vì nó là "thích hợp hơn" để thực hiện chèn?
  2. Việc truy lục giá trị danh tính có giống nhau không vì tôi đang sử dụng thông số đầu ra?
  3. Có bất kỳ lần truy cập hiệu suất nào được kết hợp với cách này hay cách khác không?
  4. Có cách nào tốt hơn để làm điều này tổng thể không?

Tôi đang sử dụng Visual Studio 2010, .NET 4.0 và SQL Server 2008r2, trong trường hợp có sự khác biệt.

+4

(1) tại sao 'ExecuteNonQuery'" thích hợp hơn "? (2) bạn đã cân nhắc sử dụng các thủ tục lưu sẵn chưa? Nếu không, tai sao không? Nó chắc chắn sẽ giúp làm sạch tất cả các quảng cáo hoc SQL bạn đang đưa vào ứng dụng của bạn - trong đó, khi bạn phải thay đổi nó, có nghĩa là bạn phải biên dịch lại và triển khai lại ứng dụng. –

+2

Hmmm ... ExecuteNonQuery thường là để thực thi SQL mà không mong đợi trả về kết quả. ExecuteScalar trả về một giá trị, do đó bạn không cần phải vượt qua các tham số. Bạn có thể thay đổi phần cuối của SQL thành 'SELECT SCOPE_IDENTITY();' sau đó sử dụng 'return (int) cmd.ExecuteScalar();' – Sam

+2

Tôi sử dụng 'ExecuteScalar' vì tôi sử dụng' SELECT SCOPE_IDENTITY' mà không có tham số đầu ra, do đó lấy một giá trị duy nhất là mục đích của 'ExecuteScalar'. http://stackoverflow.com/a/9319609/284240 –

Trả lời

25

Theo đề xuất của Aaron, một thủ tục được lưu trữ sẽ làm cho nó nhanh hơn vì nó lưu Sql Server công việc biên dịch lô SQL của bạn. Tuy nhiên, bạn vẫn có thể đi với một trong hai cách tiếp cận: ExecuteScalar hoặc ExecuteNonQuery. IMHO, sự khác biệt về hiệu suất giữa chúng quá nhỏ, một trong hai phương pháp chỉ là "đúng".

Có nói rằng, tôi không thấy điểm sử dụng ExecuteScalar nếu bạn đang lấy giá trị danh tính từ thông số đầu ra. Trong trường hợp đó, giá trị trả về bởi ExecuteScalar trở nên vô ích.

Một cách tiếp cận mà tôi thích vì nó đòi hỏi ít mã, sử dụng ExecuteScalar không có tham số đầu ra:

public static int SaveTest(Test newTest) 
{ 
    var conn = DbConnect.Connection(); 
    const string sqlString = "INSERT INTO dbo.Tests (Tester , Premise) " + 
          "    VALUES (@tester , @premise) " + 
          "SELECT SCOPE_IDENTITY()"; 
    using (conn) 
    { 
     using (var cmd = new SqlCommand(sqlString, conn)) 
     { 
      cmd.Parameters.AddWithValue("@tester", newTest.tester); 
      cmd.Parameters.AddWithValue("@premise", newTest.premise); 

      cmd.CommandType = CommandType.Text; 
      conn.Open(); 
      return (int) (decimal) cmd.ExecuteScalar(); 

     } 
    } 
} 

Chúc mừng chương trình!

EDIT: Lưu ý rằng chúng ta cần phải đúc hai lần: từ đối tượng để decimal, và sau đó đến int (nhờ techturtle cho lưu ý này).

+0

Tôi cũng gặp sự cố truyền. Nhưng đôi khi nó không cần thiết, tự hỏi tại sao? – SamChen

Các vấn đề liên quan