88

Tôi đã nhận được lỗi trên trong ứng dụng của tôi. Đây là mã gốc

public string GetCustomerNumber(Guid id)
{
     string accountNumber = 
          (string)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidmyApp, 
                          CommandType.StoredProcedure, 
                          "GetCustomerNumber", 
                          new SqlParameter("@id", id));
     return accountNumber.ToString();
 }

Tôi đã thay thế bằng

public string GetCustomerNumber(Guid id)
{
   object accountNumber =  
          (object)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidCRM, 
                                CommandType.StoredProcedure, 
                                "spx_GetCustomerNumber", 
                                new SqlParameter("@id", id));
    if (accountNumber is System.DBNull)
    {
       return string.Empty;
    }
    else
    {
       return accountNumber.ToString();
    }
}

Có cách nào tốt hơn xung quanh điều này?

|
76

Một hình thức ngắn hơn có thể được sử dụng:

return (accountNumber == DBNull.Value) ? string.Empty : accountNumber.ToString()

EDIT: Không chú ý đến ExecuteScalar. Nó thực sự trả về null nếu trường vắng mặt trong kết quả trả về. Vì vậy, sử dụng thay thế:

return (accountNumber == null) ? string.Empty : accountNumber.ToString() 
|
  • 1

    Điều đó sẽ không hoạt động - "tài khoản" không phải là một giá trị cơ sở dữ liệu mà là một đối tượng "đối tượng" Plain Old .NET thông thường - bạn cần kiểm tra đối với giá trị "null" thông thường. DBNull.Value sẽ hoạt động cho SqlDataReader hoặc SqlParameter - nhưng không phải cho đối tượng này ở đây.

    – Trịnh Thanh Ngân 20:27:40 15/05/2009
  • 1

    Bạn nói đúng, tôi bắt đầu tối ưu hóa phần kiểm tra điều kiện, chưa nhìn vào dòng trước. Mea culpa.

    – Dương Chí Công 20:28:54 15/05/2009
  • 1

    Có lỗi đánh máy trong bài viết của bạn mà tôi thực sự không thể chỉnh sửa vì chỉnh sửa yêu cầu 6 ký tự được thay đổi. Ai đó có thể thay đổi tài khoảnNumber.TosString () thành tài khoảnNumber.ToString ()

    – Võ Cao Uy 11:31:54 30/07/2013
  • 1

    @marc_s Tùy thuộc vào bố cục db / truy vấn, bạn cần kiểm tra lại một trong hai hoặc thậm chí cả hai. Nếu WHERE không khớp với bất kỳ hàng nào, bạn sẽ nhận được một null, nếu hàng được chọn có NULLtrong cột đó, giá trị trả về là System.DBNull.

    – Trịnh Liên Phương 07:52:48 27/05/2014
  • 1

    Trong trường hợp đầu tiên @Alexander đề cập - không khớp với bất kỳ hàng nào - bạn có thể dựa vào Convert.ToString hoặc bất kỳ phương thức Chuyển đổi nào khác nếu bạn ổn với giá trị họ trả về khi chuyển đổi từ null: chuỗi rỗng cho chuỗi, 0 cho giá trị số, sai cho boolean, MinValue cho DateTime ... msdn.microsoft.com/en-us/l Library / vudio / trộm

    – Tạ Gia Thịnh 14:30:16 07/10/2014
177

Với một chức năng chung đơn giản, bạn có thể làm điều này rất dễ dàng. Chỉ cần làm điều này:

return ConvertFromDBVal<string>(accountNumber);

sử dụng chức năng:

public static T ConvertFromDBVal<T>(object obj)
{
    if (obj == null || obj == DBNull.Value)
    {
        return default(T); // returns the default value for the type
    }
    else
    {
        return (T)obj;
    }
}
|
  • 1

    Vâng, một chức năng như thế này là giải pháp thực tế duy nhất. Bất kỳ loại logic nội tuyến nào cũng sẽ thất bại sau khi bạn sao chép và dán nó hàng ngàn lần. :-)

    – Trịnh Thanh Ngân 15:49:10 02/07/2009
  • 1

    điều này sẽ không hoạt động nếu bạn thử chuyển đổi 1 thành bool (Convert.ToBoolean (1) hoạt động tốt tho)

    – Dương Chí Công 20:32:02 17/10/2009
  • 1

    @roman: vì vậy sau đó chúng tôi muốn có một kiểm tra bổ sung (trước khi kiểm tra null) kiểm tra loại boolean ...

    – Võ Cao Uy 14:37:38 27/08/2010
  • 1

    Nếu bạn muốn hoặc cần sử dụng các chức năng Chuyển đổi, thì điều này không hoạt động. Có một số tình huống mà bạn có thể muốn chuyển đổi thành một diễn viên rõ ràng. @romanm lưu ý một trong số họ. Một cách khác là khi bạn làm việc với số thập phân và quan tâm đến các cơ chế làm tròn khác nhau mà Convert.ToInt32 và (int) sử dụng. Các vòng trước đến giá trị chẵn gần nhất, trong khi các biểu thức rõ ràng chỉ cắt bớt giá trị: stackoverflow.com/questions/1608801/, Nếu có thể, tôi sẽ loại bỏ NULL khỏi hỗn hợp, sử dụng hàm ISNULL của T-SQL

    – Trịnh Liên Phương 14:26:13 07/10/2014
  • 1

    @Jaime Hàm này được cho là hoạt động giống như được truyền từ kiểu dữ liệu SQL sang kiểu dữ liệu C # /. NET. Nếu bạn có nhu cầu cho một dàn diễn viên rõ ràng, đừng sử dụng chức năng này - thay vào đó hãy thực hiện nó một cách rõ ràng.

    – Tạ Gia Thịnh 22:44:58 07/10/2014
15

ExecuteScalar sẽ trở lại

  • null nếu không có tập kết quả
  • mặt khác, cột đầu tiên của hàng đầu tiên của tập kết quả, có thể là DBNull.

Nếu bạn biết rằng cột đầu tiên của tập kết quả là một chuỗi, thì để bao quát tất cả các cơ sở, bạn cần kiểm tra cả null và DBNull. Cái gì đó như:

object accountNumber = ...ExecuteScalar(...);
return (accountNumber == null) ? String.Empty : accountNumber.ToString();

Đoạn mã trên dựa trên thực tế là DBNull.ToString trả về một chuỗi rỗng.

Nếu accountNumber là một loại khác (giả sử số nguyên), thì bạn cần phải rõ ràng hơn:

object accountNumber = ...ExecuteScalar(...);
return (accountNumber == null || Convert.IsDBNull(accountNumber) ?     
         (int) accountNumber : 0;

Nếu bạn biết chắc chắn rằng tập kết quả của bạn sẽ luôn có ít nhất một hàng (ví dụ: CHỌN COUNT (*) ...), thì bạn có thể bỏ qua việc kiểm tra null.

Trong trường hợp của bạn, thông báo lỗi "Không thể truyền đối tượng thuộc loại 'System.DBNull' sang loại 'System.String`" chỉ ra rằng cột đầu tiên của tập kết quả của bạn là giá trị DBNUll. Đây là từ cast đến chuỗi trên dòng đầu tiên:

string accountNumber = (string) ... ExecuteScalar(...);

Nhận xét của Marc_s rằng bạn không cần kiểm tra DBNull. Giá trị sai.

|
6

Bạn có thể sử dụng toán tử hợp nhất null của C #

return accountNumber ?? string.Empty;
|
3

Đây là phương thức chung mà tôi sử dụng để chuyển đổi bất kỳ đối tượng nào có thể là DBNull.Value:

public static T ConvertDBNull<T>(object value, Func<object, T> conversionFunction)
{
    return conversionFunction(value == DBNull.Value ? null : value);
}

sử dụng:

var result = command.ExecuteScalar();

return result.ConvertDBNull(Convert.ToInt32);

ngắn hơn:

return command
    .ExecuteScalar()
    .ConvertDBNull(Convert.ToInt32);
|
3

Có một cách khác để khắc phục vấn đề này. Làm thế nào về sửa đổi thủ tục cửa hàng của bạn? bằng cách sử dụng hàm sql ISNULL (trường của bạn, ""), bạn có thể trả về chuỗi trống nếu giá trị trả về là null.

Sau đó, bạn có mã sạch của bạn như phiên bản gốc.

|
2

Chuyển đổi nó như

string s = System.DBNull.value.ToString();
|
2

Tôi cho rằng bạn có thể làm điều đó như thế này:

string accountNumber = DBSqlHelperFactory.ExecuteScalar(...) as string;

Nếu accountNumber là null, điều đó có nghĩa là DBNull không phải chuỗi :)

|
  • 1

    Hoặc return (accountNumber as string) ?? string.Empty;, với tài khoảnSố vẫn là một object. Nếu bạn muốn giữ cuộc gọi cơ sở dữ liệu của bạn trên dòng riêng của nó.

    – Hoàng Phụng Yến 18:10:46 30/08/2010
1

Tôi sử dụng một tiện ích mở rộng để loại bỏ vấn đề này cho tôi, có thể là hoặc không phải là những gì bạn đang theo đuổi.

Nó như thế này:

public static class Extensions
{

    public String TrimString(this object item)
    {
        return String.Format("{0}", item).Trim();
    }

}

Chú thích:

Phần mở rộng này không trả về nullgiá trị! Nếu mục là nullhoặc DBNull.Value , nó sẽ trả về một Chuỗi trống.

Sử dụng:

public string GetCustomerNumber(Guid id)
{
    var obj = 
        DBSqlHelperFactory.ExecuteScalar(
            connectionStringSplendidmyApp, 
            CommandType.StoredProcedure, 
            "GetCustomerNumber", 
            new SqlParameter("@id", id)
        );
    return obj.TrimString();
}
|
1

String.Concat biến đổi giá trị DBNull và null thành một chuỗi rỗng.

public string GetCustomerNumber(Guid id)
{
   object accountNumber =  
          (object)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidCRM, 
                                CommandType.StoredProcedure, 
                                "spx_GetCustomerNumber", 
                                new SqlParameter("@id", id));

    return String.Concat(accountNumber);

 }

Tuy nhiên, tôi nghĩ rằng bạn mất một cái gì đó về khả năng hiểu mã

|
0

Vì tôi có một ví dụ không có giá trị và nếu tôi so sánh với DBNULL, tôi đã bị loại trừ Operator '==' cannot be applied to operands of type 'string' and 'system.dbnull'và nếu tôi cố gắng thay đổi để so sánh với NULL, thì đơn giản là nó không hoạt động (vì DBNull là một đối tượng) ngay cả đó là câu trả lời được chấp nhận.

Tôi quyết định chỉ cần sử dụng từ khóa 'là'. Vì vậy, kết quả là rất dễ đọc:

data = (item is DBNull) ? String.Empty : item

|

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.