[c#] ‘System.DBNull’유형의 개체를 ‘System.String’유형으로 캐스팅 할 수 없습니다.

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

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

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



답변

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

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

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

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


답변

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

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


답변

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의 의견이 잘못되었습니다.


답변

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

return accountNumber ?? string.Empty;


답변

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

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


답변

이것은 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);


답변

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

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

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