Данные пустые.Этот метод или свойство нельзя вызывать для значений Null - PullRequest
42 голосов
/ 15 марта 2012

Я работаю над приложением, в котором можно получать информацию о фильмах из базы данных, а также добавлять, обновлять и удалять фильмы. В базе данных у меня есть три таблицы (Movie, Genre и MovieGenre <- хранит фильмы и их жанры). Все отлично работает, кроме одной вещи, и именно тогда у фильма нет жанров (что должно быть возможно). </p>

Проблема возникает в методе ниже, и выдается следующее исключение: Данные равны нулю. Этот метод или свойство нельзя вызывать для значений Null.

Причина (конечно) в том, что sproc возвращает ноль, потому что у фильма нет жанров, но я просто не могу понять, как предотвратить это исключение. Как я уже сказал, должна быть возможность хранить фильм без какой-либо информации жанра.

Заранее спасибо!

Метод:

public List<MovieGenre> GetMovieGenrebyMovieID(int movieID) {

    using (SqlConnection conn = CreateConnection()) {
        try {

            SqlCommand cmd = new SqlCommand("dbo.usp_GetMovieGenreByMovieID", conn);
            cmd.CommandType = CommandType.StoredProcedure;

            cmd.Parameters.AddWithValue("@MovieID", movieID);

            List<MovieGenre> movieGenre = new List<MovieGenre>(10);

            conn.Open();

            using (SqlDataReader reader = cmd.ExecuteReader()) {

                int movieGenreIDIndex = reader.GetOrdinal("MovieGenreID");
                int movieIDIndex = reader.GetOrdinal("MovieID");
                int genreIDIndex = reader.GetOrdinal("GenreID");

                while (reader.Read()) {

                    movieGenre.Add(new MovieGenre {
                        MovieID = reader.GetInt32(movieIDIndex),
                        MovieGenreID = reader.GetInt32(movieGenreIDIndex),
                        GenreID = reader.GetInt32(genreIDIndex)
                    });
                }
            }

            movieGenre.TrimExcess();

            return movieGenre;
        }
        catch {
            throw new ApplicationException();
        }
    }
}

Спрок:

ALTER PROCEDURE usp_GetMovieGenreByMovieID
@MovieID int
AS
BEGIN
    BEGIN TRY
        SELECT m.MovieID, g.GenreID, mg.MovieGenreID, g.Genre
        FROM Movie AS m
        LEFT JOIN MovieGenre AS mg
            ON m.MovieId = mg.MovieID
        LEFT JOIN Genre AS g
            ON mg.GenreID = g.GenreID
        WHERE m.MovieID = @MovieID
    END TRY
    BEGIN CATCH
        RAISERROR ('Error while trying to receive genre(s).',16,1)
    END CATCH
END

Ответы [ 3 ]

60 голосов
/ 15 марта 2012

Вы не должны пытаться преобразовать нулевые значения из процедуры в целые, поэтому перед созданием экземпляра MovieGenre необходимо проверить поля, допускающие значения NULL, используя метод SqlDataReader.IsDBNull:

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.isdbnull.aspx

Предполагая, что GenreID и MovieGenreID являются обнуляемыми целыми числами, вы можете сделать что-то вроде:

movieGenre.Add(new MovieGenre {
  MovieID = reader.GetInt32(movieIDIndex),
  MovieGenreID = reader.IsDBNull(movieGenreIDIndex) ? null : reader.GetInt32(movieGenreIDIndex),
  GenreID = reader.IsDBNull(genreIDIndex) ? null : reader.GetInt32(genreIDIndex)
});
7 голосов
/ 15 марта 2012

Отредактируйте оператор select следующим образом, чтобы обработать нулевую проблему.

SELECT ISNULL(m.MovieID,0) AS MovieID, 
       ISNULL(g.GenreID,0) AS GenreID, 
       ISNULL(mg.MovieGenreID,0) AS MovieGenreID,
       ISNULL(g.Genre,'') AS Genre
FROM --rest of your query...
2 голосов
/ 15 марта 2012

Самый простой ответ - заменить пустые значения ненулевыми. Попробуйте:

ALTER PROCEDURE usp_GetMovieGenreByMovieID
@MovieID int
AS
BEGIN
    BEGIN TRY
        SELECT m.MovieID, 
               coalesce(g.GenreID,0) GenreID, 
               coalesce(mg.MovieGenreID,0) MovieGenreID, 
               coalesce(g.Genre, 'Not Applicable') Genre
        FROM Movie AS m
        LEFT JOIN MovieGenre AS mg
            ON m.MovieId = mg.MovieID
        LEFT JOIN Genre AS g
            ON mg.GenreID = g.GenreID
        WHERE m.MovieID = @MovieID
    END TRY
    BEGIN CATCH
        RAISERROR ('Error while trying to receive genre(s).',16,1)
    END CATCH
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...