2012-11-19 37 views
55

Tôi có mã sau để chỉ định tham số cho truy vấn SQL. Tôi nhận được ngoại lệ sau khi tôi sử dụng Code 1; nhưng hoạt động tốt khi tôi sử dụng Code 2. Trong Code 2 chúng tôi có một kiểm tra cho null và do đó một khối if..else.Ngoại lệ khi tham số AddWithValue là NULL

Ngoại lệ:

Truy vấn tham số '(nvarchar @application_ex_id (4000)) CHỌN E.application_ex_id A' hy vọng tham số '@application_ex_id', mà đã không được cung cấp.

Mã 1:

command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 

Mã 2:

if (logSearch.LogID != null) 
{ 
     command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 
} 
else 
{ 
     command.Parameters.AddWithValue("@application_ex_id", DBNull.Value); 
} 

HỎI

  1. Bạn có thể giải thích tại sao không thể lấy NULL từ giá trị logSearch.LogID trong Mã 1 (nhưng có thể chấp nhận DBNull) không?

  2. Có mã nào tốt hơn để xử lý việc này không?

Reference:

  1. Assign null to a SqlParameter
  2. Datatype returned varies based on data in table
  3. Conversion error from database smallint into C# nullable int
  4. What is the point of DBNull?

CODE

public Collection<Log> GetLogs(LogSearch logSearch) 
    { 
     Collection<Log> logs = new Collection<Log>(); 

     using (SqlConnection connection = new SqlConnection(connectionString)) 
     { 
      connection.Open(); 

      string commandText = @"SELECT * 
       FROM Application_Ex E 
       WHERE (E.application_ex_id = @application_ex_id OR @application_ex_id IS NULL)"; 

      using (SqlCommand command = new SqlCommand(commandText, connection)) 
      { 
       command.CommandType = System.Data.CommandType.Text; 

       //Parameter value setting 
       //command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 
       if (logSearch.LogID != null) 
       { 
        command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 
       } 
       else 
       { 
        command.Parameters.AddWithValue("@application_ex_id", DBNull.Value); 
       } 

       using (SqlDataReader reader = command.ExecuteReader()) 
       { 
        if (reader.HasRows) 
        { 
         Collection<Object> entityList = new Collection<Object>(); 
         entityList.Add(new Log()); 

         ArrayList records = EntityDataMappingHelper.SelectRecords(entityList, reader); 

         for (int i = 0; i < records.Count; i++) 
         { 
          Log log = new Log(); 
          Dictionary<string, object> currentRecord = (Dictionary<string, object>)records[i]; 
          EntityDataMappingHelper.FillEntityFromRecord(log, currentRecord); 
          logs.Add(log); 
         } 
        } 

        //reader.Close(); 
       } 
      } 
     } 

     return logs; 
    } 
+3

Ý anh là gì bởi tốt hơn? Mã 2 là cách chính xác để gửi một giá trị null đến một cơ sở dữ liệu. –

+0

Tham khảo: http://stackoverflow.com/questions/13265704/conversion-error-from-database-smallint-into-c-sharp-nullable-int – Lijo

Trả lời

84

Bực mình, đúng không.

Bạn có thể sử dụng:

command.Parameters.AddWithValue("@application_ex_id", 
     ((object)logSearch.LogID) ?? DBNull.Value); 

Hoặc cách khác, sử dụng một công cụ như "đoan trang", mà sẽ làm tất cả những gì rối tung cho bạn.

Ví dụ:

var data = conn.Query<SomeType>(commandText, 
     new { application_ex_id = logSearch.LogID }).ToList(); 

Tôi cám dỗ để thêm một phương pháp để Dapper để có được những IDataReader ... không thực sự chắc chắn nhưng cho dù đó là một ý tưởng tốt.

+0

@Phil thực sự; hầu hết mọi thứ đều có thể ... nhưng tôi không thích thêm các phương thức mở rộng vào 'đối tượng', và chúng ta không thể biết đó là' Nullable 'vs' string', v.v ... nhưng có: nó có thể được thực hiện dễ dàng đủ. –

+1

Tôi đã suy nghĩ một phần mở rộng trên thuộc tính 'Parameters' - là một' Object'? –

+3

@Phil hmmm, vâng, và tôi hiểu ý của bạn ... có lẽ 'AddWithValueAndTreatNullTheRightDamnedWay (...)' –

1

một số vấn đề, cho phép với Hẳn thiết SQLDbType

command.Parameters.Add("@Name", SqlDbType.NVarChar); 
command.Parameters.Value=DBNull.Value 

nơi SqlDbType.NVarChar bạn gõ. Cần thiết đặt loại SQL. Enjou

34

Tôi tìm thấy nó dễ dàng hơn để chỉ cần viết một phương pháp khuyến nông cho người SqlParameterCollection để xử lý các giá trị null:

public static SqlParameter AddWithNullableValue(
    this SqlParameterCollection collection, 
    string parameterName, 
    object value) 
{ 
    if(value == null) 
     return collection.AddWithValue(parameterName, DBNull.Value); 
    else 
     return collection.AddWithValue(parameterName, value); 
} 

Sau đó, bạn chỉ cần gọi nó thích:

sqlCommand.Parameters.AddWithNullableValue(key, value); 
+0

_value_ có thể là ** int hoặc int ?, string, bool hoặc bool ?, DateTime hoặc Datetime? **, v.v ...? – Kiquenet

+0

@Kiquenet Có ... – AxiomaticNexus

+2

Tôi đọc câu trả lời của Marc và nghĩ rằng "Tôi nghĩ tôi chỉ muốn viết một phương pháp mở rộng cho bộ sưu tập Tham số", sau đó tôi cuộn xuống tóc ... (điều tốt về phương pháp mở rộng là Tôi có thể thực hiện một lần tìm/thay thế sau và tất cả các cập nhật mã của tôi được thực hiện) – jleach

2

Chỉ trong trường hợp bạn' đang làm điều này trong khi gọi một thủ tục được lưu trữ: Tôi nghĩ rằng nó dễ dàng hơn để đọc nếu bạn khai báo một giá trị mặc định trên tham số và thêm nó chỉ khi cần thiết.

Ví dụ: (sql)

DECLARE PROCEDURE myprocedure 
    @myparameter [int] = NULL 
AS BEGIN 

(C#)

int? myvalue = initMyValue(); 
if (myvalue.hasValue) cmd.Parameters.AddWithValue("myparamater", myvalue); 

Tôi biết điều này là cũ, nhưng tôi thấy hữu ích này và muốn chia sẻ.

-3

Tạo một lớp tĩnh như thế này:

public static class Extensions 
{ 
    public static string RemoveNulls(this string container) 
    { 
     if (container == null) 
      container = ""; 
     return container; 
    } 
} 

Sau đó, trong mã của bạn, làm điều này:

Parameters.AddWithValue(sName, Value.RemoveNulls()); 

Đây là viên đạn bằng chứng và rất dễ sử dụng

+1

Điều này sẽ chèn "" và không rỗng ... – Lars

+0

Đó là những gì anh ta muốn - không được nhập một giá trị rỗng – TheWizardOfTN

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