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