with storedprocedure stored net llamar ejecutar desde commandtype asp and c# asp.net sql stored-procedures

c# - storedprocedure - Los datos son nulos. Este método o propiedad no se puede invocar en valores nulos



llamar stored procedure desde c# (3)

Edite su instrucción de selección de la siguiente manera para manejar un problema nulo.

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

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 las 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).

El problema se produce en el siguiente método y se produce la siguiente excepción: Data is Null. 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 entender cómo 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 por adelantado!

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


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

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


No debe intentar convertir los valores nulos del proceso en ints, por lo que antes de crear la instancia de MovieGenre debe verificar los campos que aceptan valores de nulo mediante el método SqlDataReader.IsDBNull :

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

Asumiendo que el GenreID y el MovieGenreID son anulables, podrías 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) });