2012-03-15 35 views
34

我正在研究可以從數據庫獲取電影信息以及添加,更新和刪除電影的應用程序。在數據庫中,我有三個表格(電影,流派和電影世界< - 存儲電影及其流派)。除了一件事以外,一切都可以正常工作,那就是當一部電影沒有任何流派時(這應該是可能的)。數據爲空。無法在空值上調用此方法或屬性

問題發生在下面的方法中,並拋出以下異常: 數據爲空。無法在Null值上調用此方法或屬性。

原因(當然)是由於影片沒有任何流派,影片會返回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(); 
     } 
    } 
} 

的存儲過程:

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

此:'抓{拋出新的申請icationException(); }'是一個非常糟糕的主意。你正在失去所有的上下文信息。至少通過捕獲的異常作爲內部異常:catch(Exception ex){throw new ApplicationException(ex); }' – 2012-03-15 12:30:57

回答

47

你不應該試圖將空值從PROC轉換成整數 - 讓你創建MovieGenre實例之前,你需要使用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

您可能需要將代碼添加爲reader.IsDBNull( movieGenreIDIndex)? (int?)null:reader.GetInt32(movieGenreIDIndex) – akd 2015-04-09 12:10:49

5

編輯如下處理空問題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... 
+0

感謝您的回答。我嘗試了你的代碼,但不幸的是我得到了同樣的錯誤:/ – holyredbeard 2012-03-15 12:40:00

+0

我只用ISNULL爲GenreID和Genre列向你展示。你可以使用它作爲每個列**答案更新爲包括所有列** – Kaf 2012-03-15 12:46:51

2

最簡單的答案是用非空值替換空值。嘗試:

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+ for'coalesce'' ISNULL'不適用於我我使用MySql – ygaradon 2014-04-02 18:03:46

相關問題