数据是空的。无法在Null值上调用此方法或属性

时间:2012-03-15 12:28:23

标签: c# asp.net sql stored-procedures

我正在开发一个应用程序,可以从数据库中获取有关电影的信息,以及添加,更新和删除电影。在数据库中,我有三个表(电影,流派和MovieGenre< - 存储电影及其类型)。除了一件事,一切都很好,那就是电影没有任何类型(这应该是可能的)。

问题出现在下面的方法中,并抛出以下异常: 数据是空的。无法在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();
        }
    }
}

简介:

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

8 个答案:

答案 0 :(得分:59)

您不应该尝试将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)
});

答案 1 :(得分:10)

在我在实体框架核心3.1项目中启用C#8可为空功能后,立即发生此错误。

解决方案是将您的实体属性更改为可为空的对应属性。例如,

更改自:

import path1 from '../myGif.gif'
renderGif(show) {
    //set myGif and styleToDisplay for the case where
    //the div will be shown
    let myGif = path1
    var styleToDisplay = {
        position:"absolute",
    }

    //if div will not be shown, set div to hidden and 
    //myGif=""
    if (!show) {
        myGif = ""
        styleToDisplay = {display: "none"}
    }

    //instead of just returning null here when div 
    //is not shown, return a hidden div where myGif = ""
    return(
        <div
            onClick={this.toggleShow}
            style={styleToDisplay}>

            <img src={myGif} width="250px" height="250px"/>
        </div>
    );
}


toggleShow = () => {
    let t = this.state.show
    this.setState({
        show: !t,
    })
}

//call this function from another component 
//or wherever you want to show the gif
showGif () => {
    this.setState({
        show: true,
    })
}

//main render function
render() {
    return (
        {this.renderGif(this.state.show}
    )
}

收件人:

public class Person {
  public int Id { get; set; }
  public string Name { get;set; }
  public string Address { get;set; }
}

答案 2 :(得分:7)

按如下方式编辑select语句以处理null问题。

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

答案 3 :(得分: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

答案 4 :(得分:2)

在我的情况下,我使用的是EF Core,问题是该字段在数据库中为空,但在ModelCreating中则需要这样:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   modelBuilder.Entity<MyEntity>(entity =>
   {
      entity.Property(e => e.Details)
                    .IsRequired()
                    .HasMaxLength(250);
   }
}

我删除了IsRequired(),它工作正常。

几天后更新, 遇到同样的问题,一个字符串字段。数据库中不允许为空。

答案 5 :(得分:0)

BookingQuantity-DB中具有空值的列。但是实际的DB BookingQuantity不能为空列。碰巧会遇到一些罕见的情况。在这种情况下,下面的代码将引发错误,并且出现相同的错误(数据为Null。无法在Null值上调用此方法或属性 )。

totalBookingQuantity += item.InspPoTransactions.Where(x => x.PoId == inspectionPODetail.PoId && x.ProductId == inspectionPODetail.ProductId).Sum(x => Convert.ToInt32(x.BookingQuantity));

答案 6 :(得分:0)

今天,我遇到了这个问题。但是我的问题已经用另一种方式解决了。如果有一天有人绊倒了,答案就是他们。

这是一个通用的C#.NET CLI异常

我已经向我的数据库表之一添加了新的外键,没有默认值。因此,将值设置为tk.mainloop(),因为该列设置为允许为空。 而且我在查询该表时一直遇到这种异常。

作为解决方案,我用适当的值替换了NULL值(因为它们是外键,所以应该适当)。

仅此而已。

谢谢。

答案 7 :(得分:0)

对我来说这是因为在数据库中有一个列 'XYZ',它有一个 NULL 值,但映射到它的模型的属性 (bool) 不可为空。