私は、データベースから映画に関する情報を取得したり、映画を追加、更新、削除できるアプリケーションを開発しています。データベースには3つのテーブルがあります(Movie、Genre、MovieGenre <-映画とそのジャンルを保存します)。 1つだけでなく、すべてが正常に機能します。そのとき、映画にはジャンルがありません(可能なはずです)。
以下のメソッドで問題が発生し、次の例外がスローされます。データはNULLです。このメソッドまたはプロパティは、NULL値で呼び出すことはできません。
(もちろん)理由は、映画にジャンルがないためsprocがnullを返すためですが、この例外がスローされるのを防ぐ方法がわかりません。私が言ったように、ジャンルの情報を保存せずに映画を保存することが可能であるべきです。
前もって感謝します!
メソッド:
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();
}
}
}
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
Procのnull値をintに変換しようとするべきではありません。したがって、MovieGenreインスタンスを作成する前に、SqlDataReader.IsDBNull
メソッドを使用してnull値を許可するフィールドを確認する必要があります。
http://msdn.Microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.isdbnull.aspx
CategoriesIDとMovieGenreIDがnull入力可能な整数であると仮定すると、次のようなことができます。
movieGenre.Add(new MovieGenre {
MovieID = reader.GetInt32(movieIDIndex),
MovieGenreID = reader.IsDBNull(movieGenreIDIndex) ? null : reader.GetInt32(movieGenreIDIndex),
GenreID = reader.IsDBNull(genreIDIndex) ? null : reader.GetInt32(genreIDIndex)
});
Nullの問題を処理するには、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...
最も簡単な答えは、ヌルをヌル以外の値に置き換えることです。試してください:
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