C# 数据为空。不能对 Null 值调用此方法或属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9719683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Data is Null. This method or property cannot be called on Null values
提问by holyredbeard
I'm working on an application where one can get information on movies from a database as well as add, update and delete the movies. In the database I have three tables (Movie, Genre and MovieGenre <- stores the movies and their genre/s). Everything works fine besides one thing, and that's when a movie hasn't got any genres (which should be possible).
我正在开发一个应用程序,可以从数据库中获取电影信息以及添加、更新和删除电影。在数据库中,我有三个表(电影、流派和电影流派 <- 存储电影及其流派)。除了一件事之外,一切都很好,那就是电影没有任何类型(这应该是可能的)。
The problem occur in the method below, and the following exception is thrown: Data is Null. This method or property cannot be called on Null values.
问题出现在下面的方法中,并抛出以下异常: Data is Null。不能对 Null 值调用此方法或属性。
The reason (of course) is that the sproc returns null because the movie hasn't got any genres, but I just can't figure out how to prevent this exception being thrown. As I said, it should be possible to store a movie without storing any information of genre/s.
原因(当然)是 sproc 返回 null 因为电影没有任何类型,但我只是不知道如何防止抛出这个异常。正如我所说,应该可以在不存储任何类型信息的情况下存储电影。
Thanks in advance!
提前致谢!
The method:
方法:
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();
}
}
}
The 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
采纳答案by kaj
You shouldn't be trying to convert the null values from the proc into ints - so before you create the MovieGenre instance you need to check the nullable fields using the SqlDataReader.IsDBNullmethod:
您不应该尝试将 proc 中的空值转换为整数 - 因此在创建 MovieGenre 实例之前,您需要使用以下SqlDataReader.IsDBNull方法检查可为空的字段:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.isdbnull.aspx
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.isdbnull.aspx
Assuming that the GenreID and MovieGenreID are nullable ints you could do something like:
假设 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)
});
回答by Kaf
Edit your select statement as follows to handle null issue.
按如下方式编辑您的选择语句以处理空问题。
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...
回答by Kaf
The simplest answer is to replace the nulls with non-null values. Try:
最简单的答案是用非空值替换空值。尝试:
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
回答by Ronika
BookingQuantity - column having null value in DB. but actual DB BookingQuantity not null column. Some rare case it happens to enter. In that case below code throw error the same error(Data is Null. This method or property cannot be called on Null values).
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));
totalBookingQuantity += item.InspPoTransactions.Where(x => x.PoId == inspectionPODetail.PoId && x.ProductId == inspectionPODetail.ProductId).Sum(x => Convert.ToInt32(x.BookingQuantity));
回答by Rosdi Kasim
This error happens immediately after I enabled C# 8 nullablefeature in my Entity Framework Core 3.1 project.
在我的 Entity Framework Core 3.1 项目中启用 C# 8 可为空功能后,立即发生此错误。
The solution is to change your entity properties to their nullable counterparts. For example,
解决方案是将您的实体属性更改为其可为空的对应物。例如,
Change from:
更改自:
public class Person {
public int Id { get; set; }
public string Name { get;set; }
public string Address { get;set; }
}
To:
到:
public class Person {
public int Id { get; set; }
public string Name { get;set; }
public string? Address { get;set; } //change address to nullable string since it is nullable in database
}

