2012-03-15 26 views
34

Estoy trabajando en una aplicación donde se puede obtener información sobre películas de una base de datos, así como agregar, actualizar y eliminar películas. En la base de datos tengo tres tablas (Movie, Genre y MovieGenre < - almacena las películas y su género/s). Todo funciona bien, además de una cosa, y es cuando una película no tiene ningún género (que debería ser posible).Los datos son nulos. No se puede llamar a este método o propiedad en Valores nulos

El problema se produce en el método siguiente y se produce la siguiente excepción: Los datos son nulos. Este método o propiedad no se puede invocar en valores nulos.

La razón (por supuesto) es que el sproc devuelve nulo porque la película no tiene ningún género, pero no puedo encontrar la manera de evitar que se produzca esta excepción. Como dije, debería ser posible almacenar una película sin almacenar ninguna información de género/s.

¡Gracias de antemano!

El método:

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

El sproc:

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 
+9

Este: 'catch {throw new Appl icationException(); } 'es una muy mala idea. Estás perdiendo TODA la información de contexto. Al menos pase la excepción detectada como excepción interna: 'catch (Exception ex) {throw new ApplicationException (ex); } ' –

Respuesta

47

Usted no debe estar tratando de convertir los valores nulos de la proc en enteros - por lo que antes de crear la instancia MovieGenre es necesario comprobar los campos anulables utilizando el método SqlDataReader.IsDBNull:

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

Suponiendo que el GenreID y MovieGenreID son enteros con valores nulos que podría hacer algo como:

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

puede que necesite agregar el código como reader.IsDBNull (películaGenreIDIndex)? (int?) null: reader.GetInt32 (movieGenreIDIndex) – akd

5

Editar su instrucción de selección de la siguiente manera para manejar tema nula.

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... 
+0

Gracias por responder. Probé tu código pero desafortunadamente recibo el mismo error:/ – holyredbeard

+0

Utilicé ISNULL solo para las columnas GenreID y Género para mostrarte. Puede usarlo para cada columna como ** RESPUESTA ACTUALIZADA PARA INCLUIR TODAS LAS COLUMNAS ** – Kaf

2

La respuesta más simple es reemplazar los nulos con valores no nulos. Proveedores:

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 
+0

1+ para 'coalesce'' ISNULL' no funciona para mí uso MySql – ygaradon

Cuestiones relacionadas