'System.DBNull'유형의 개체를 'System.String'유형으로 캐스팅 할 수 없습니다.


109

내 앱에서 위의 오류가 발생했습니다. 다음은 원래 코드입니다.

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

나는

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();
    }
}

이 문제를 해결하는 더 좋은 방법이 있습니까?


2
당신은 정말로 @rein의 대답을 조사해야합니다. 장기적으로 많은 시간을 절약 할 것입니다
roman m

답변:


90

더 짧은 형식을 사용할 수 있습니다.

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

편집 : ExecuteScalar에주의를 기울이지 않았습니다. 반환 결과에 필드가 없으면 실제로 null을 반환합니다. 따라서 대신 사용하십시오.

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

3
그것은하지 않습니다 작업 -은 "이 accountNumber는" 하지 데이터베이스 값하지만 정기적 된 일반 올드 .NET "개체"예 - 당신이 정상 "NULL"값에 대해 확인해야합니다. DBNull.Value는 SqlDataReader 또는 SqlParameter에 대해서는 작동하지만 여기에서는이 개체에 대해서는 작동하지 않습니다.
marc_s

당신 말이 맞아요, 저는 상태 점검 부분을 최적화하기 시작했고, 전에 라인을 보지 않았습니다. Mea culpa.
사용자

게시물에 수정을하려면 6 글자가 필요하기 때문에 수정할 수없는 오타가 있습니다. 누군가 accountNumber.TosString ()을 accountNumber.ToString ()으로 변경할 수 있습니까
Eric

@marc_s db / query 레이아웃에 따라 둘 중 하나 또는 둘 다에 대해 확인해야합니다. WHERE가 어떤 행과도 일치하지 않으면를 얻습니다 null. 선택한 행이 NULL해당 열에 있으면 반환 값은 System.DBNull입니다.
Alexander

첫 번째 경우 @Alexander가 언급 한-행과 일치하지 않음-null에서 변환 할 때 반환하는 값에 문제가 없으면 Convert.ToString 또는 다른 Convert 메서드를 사용할 수 있습니다. 문자열의 경우 빈 문자열, 숫자 값의 경우 0, false 부울, MINVALUE에 대한 날짜 시간 ... msdn.microsoft.com/en-us/library/vstudio/...은
제이미

199

간단한 일반 함수를 사용하면이를 매우 쉽게 만들 수 있습니다. 다음과 같이하십시오.

return ConvertFromDBVal<string>(accountNumber);

기능 사용 :

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
예, 이와 같은 기능이 유일한 실용적인 솔루션입니다. 모든 종류의 인라인 논리는 복사하여 수천 번 붙여 넣으면 실패합니다. :-)
Christian Hayter

3
1을 bool로 변환하려고하면 작동하지 않습니다 (Convert.ToBoolean (1)은 잘 작동합니다)
roman m

@roman : 그래서 우리는 부울 유형을 검사하는 추가 검사 (null 검사 전)를 원할 것입니다 ...
IAbstract

1
변환 기능을 원하거나 사용해야하는 경우 작동하지 않습니다. 명시 적 캐스트로 변환하는 것을 선호 할 수있는 몇 가지 시나리오가 있습니다. @romanm이 그중 하나를 언급했습니다. 또 다른 하나는 소수점으로 작업하고 Convert.ToInt32 및 (int)에서 사용하는 다양한 반올림 메커니즘에 관심을 가질 때입니다. 전자는 가장 가까운 짝수 값으로 반올림하고 명시 적 캐스트는 값을 자릅니다. stackoverflow.com/questions/1608801/… 가능하면 T-SQL ISNULL 함수를 사용하여 혼합에서 NULL을 제거합니다
Jaime

2
@Jaime이 함수는 SQL 데이터 유형에서 C # /. NET 데이터 유형으로의 암시 적 캐스트처럼 작동합니다. 명시 적 캐스트가 필요한 경우이 함수를 사용하지 말고 대신 명시 적으로 수행하십시오.
고삐

17

ExecuteScalar가 반환합니다.

  • 결과 집합이 없으면 null
  • 그렇지 않으면 결과 집합의 첫 번째 행의 첫 번째 열이며 DBNull 일 수 있습니다.

결과 집합의 첫 번째 열이 문자열이라는 것을 알고있는 경우 모든 염기를 포함하려면 null과 DBNull을 모두 확인해야합니다. 다음과 같은 것 :

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

위의 코드는 DBNull.ToString이 빈 문자열을 반환한다는 사실에 의존합니다.

accountNumber가 다른 유형 (예 : 정수)이면 더 명확해야합니다.

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

결과 집합에 항상 하나 이상의 행이 있다는 것을 알고있는 경우 (예 : SELECT COUNT (*) ...) null 검사를 건너 뛸 수 있습니다.

귀하의 경우 " 'System.DBNull'유형의 개체를 'System.String'유형으로 캐스팅 할 수 없습니다"라는 오류 메시지는 결과 집합의 첫 번째 열이 DBNUll 값임을 나타냅니다. 이것은 첫 번째 줄의 캐스트에서 문자열로입니다.

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

DBNull.Value를 확인할 필요가 없다는 Marc_s의 의견이 잘못되었습니다.


내 결과 집합이 항상 행을 반환하지는 않습니다.
Saif Khan

6

C #의 Null 병합 연산자를 사용할 수 있습니다.

return accountNumber ?? string.Empty;

-1 : 컴파일되지 않습니다. 메서드는 문자열을 반환하고 accountNumber는 객체입니다.
Joe

2
return Cmd.ExecuteScalar (). ToString () ?? String.Empty;
Chaitanya

. 수익 Cmd.ExecuteScalar의 toString ()는 () 나를 위해 일을했다
타란

3

이 문제를 해결하는 다른 방법이 있습니다. 저장 절차를 수정하는 것은 어떻습니까? ISNULL (your field, "") sql function을 사용하여 반환 값이 null 인 경우 빈 문자열을 반환 할 수 있습니다.

그런 다음 깨끗한 코드를 원본 버전으로 얻습니다.


3

이것은 DBNull.Value 일 수있는 모든 개체를 변환하는 데 사용하는 일반 메서드입니다.

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

용법:

var result = command.ExecuteScalar();

return result.ConvertDBNull(Convert.ToInt32);

더 짧게 :

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

2

다음과 같이 할 수 있다고 가정합니다.

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

accountNumber가 null이면 문자열이 아닌 DBNull임을 의미합니다. :)


또는 return (accountNumber as string) ?? string.Empty;accountNumber가 여전히 object. 데이터베이스 호출을 자체 회선에서 유지하려는 경우.
Brian

1

String.Concat은 DBNull 및 null 값을 빈 문자열로 변환합니다.

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

    return String.Concat(accountNumber);

 }

그러나 나는 당신이 코드 이해력에 뭔가를 잃어버린 것 같아요


1
글을 쓰면 return "" + accountNumber;어떻게 되나요?
Zev Spitz 2014

0

null이 아닌 인스턴스를 얻었으므로 DBNULL과 비교하면 Operator '==' cannot be applied to operands of type 'string' and 'system.dbnull' 했으며 NULL과 비교하려고하면 DBNull이 개체이기 때문에 작동하지 않았습니다.

나는 단순히 'is'키워드를 사용하기로 결정했습니다. 따라서 결과는 매우 읽기 쉽습니다.

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


-1

확장 기능을 사용하여이 문제를 제거합니다.

다음과 같이 진행됩니다.

public static class Extensions
{

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

}

노트 :

이 확장 null 값을 반환 하지 않습니다 ! 항목이 null또는 DBNull.Value 이면 빈 문자열을 반환합니다.

용법:

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.