数据为空。不能对 Null 值调用此方法或属性

Posted

技术标签:

【中文标题】数据为空。不能对 Null 值调用此方法或属性【英文标题】:Data is Null. This method or property cannot be called on Null values 【发布时间】:2012-03-31 22:59:51 【问题描述】:

我正在开发一个应用程序,可以从数据库中获取有关电影的信息以及添加、更新和删除电影。在数据库中,我有三个表(电影、流派和电影流派

问题出现在下面的方法中,抛出如下异常:

原因(当然)是 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

【问题讨论】:

这个:catch throw new ApplicationException(); 是一个非常糟糕的主意。您正在丢失所有上下文信息。至少将捕获的异常作为内部异常传递:catch(Exception ex) throw new ApplicationException(ex); 【参考方案1】:

您不应该尝试将 proc 中的 null 值转换为整数 - 因此在创建 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)
);

【讨论】:

您可能需要将代码添加为 reader.IsDBNull(movieGenreIDIndex) ? (int?)null : reader.GetInt32(movieGenreIDIndex) 如何找出错误发生在哪个属性上?【参考方案2】:

在我的 Entity Framework Core 3.1 项目中启用 C# 8 nullable 功能后立即发生此错误。

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

更改自:

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


收件人:

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


【讨论】:

string 可以为空。 @Jocie 我指的是新的 C# 8 可空引用类型。 docs.microsoft.com/en-us/dotnet/csharp/nullable-references,这里string 可以是stringstring? 我在我的回答中加粗了这个措辞,以使其更清晰。 这很有趣,我想知道为什么当string 已经可以为空时你需要这样做。不过很好找。 @Vitani,这似乎是一个用词不当的问题。 String 还不能为空(即Nullable&lt;string&gt;),它只是一个class,它是一个引用类型,而不是一个struct,它是一个值类型。突然之间,我们需要在所有这些引用类型之后明确地加上一个问号。我仍然对究竟是为什么有点模糊..【参考方案3】:

编辑您的选择语句如下处理空问题。

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

【讨论】:

感谢您的回答。我试过你的代码,但不幸的是我得到了同样的错误:/ 我仅将 ISNULL 用于 GenreID 和 Genre 列以向您展示。您可以将它作为 ANSWER UPDATED TO INCLUDE ALL COLUMNS 用于每一列 如果你使用 mysql,你必须使用IFNULL【参考方案4】:

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

protected override void OnModelCreating(ModelBuilder modelBuilder)

   modelBuilder.Entity<MyEntity>(entity =>
   
      entity.Property(e => e.Details)
                    .IsRequired()
                    .HasMaxLength(250);
   

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

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

【讨论】:

另外,如果您在模型生成器中没有.IsRequired(),您可以在您的实体中检查[Required] 注释【参考方案5】:

最简单的答案是用非空值替换空值。试试:

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

【讨论】:

1+ for coalesce ISNULL 不适合我我使用 MySql【参考方案6】:

如果有人遇到过这个问题,这就是我的情况。

我正在构建 WEB Api。在我设置 [Required] Attribue - https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.requiredattribute?view=net-5.0 之前,我的数据库中有一些 NULL 值。然后我将此属性添加到我的模型并尝试发出 GET 请求,但是 "System.InvalidOperationException: The data is NULL at ordinal 1. 此方法不能在 NULL 值上调用。在调用之前使用 IsDBNull 检查。” 出现了。

所以我从数据库中删除了 NULL 值,之后每个请求都运行良好。 据我了解,发生错误是因为 EF Core 不允许在数据库中使用 NULL 值,而 [必需]应用属性。

我希望它对某人有所帮助。

【讨论】:

虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review【参考方案7】:

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

【讨论】:

【参考方案8】:

我在 .net5 数据优先项目中遇到了这个问题,因为数据库中的一个字段可以为空,但在 c# 实体类中是必需的。通过 ef core power tools 扩展重新创建实体后,问题解决了。

【讨论】:

【参考方案9】:

BookingQuantity - DB 中具有空值的列。但实际数据库 BookingQuantity 不是空列。它碰巧进入了一些罕见的情况。在这种情况下,下面的代码会抛出相同的错误(数据为 Null。无法在 Null 值上调用此方法或属性 )。

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

【讨论】:

【参考方案10】:

今天我遇到了这个问题。但是我的已经以另一种方式修复了。如果有一天有人偶然发现答案是给他们的。

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

我在我的一个数据库表中添加了一个没有默认值的新外键。因此,该值被设置为NULL,因为该列被设置为允许为空。 我在查询该表时遇到了这个异常。

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

就是这样。

谢谢。

【讨论】:

【参考方案11】:

此错误可能是由于用户对数据库的权限不足。检查用户是否至少具有 EXECUTE、SELECT 或 SHOW DATABASES 权限

【讨论】:

以上是关于数据为空。不能对 Null 值调用此方法或属性的主要内容,如果未能解决你的问题,请参考以下文章

System.Data.SqlTypes.SqlNullValueException: 数据为空。不能对空值调用此方法或

SQL Server 复制本地订阅属性返回“无法将值‘null’应用于属性 ServerInstance:值不能为空。”

okhttppost表单请求参数为null过滤

mysql基础2

请教:C# WebService调用Java WebService(返回Json类型数据) ,为啥接收为null

java中怎么判断long是不是为"" 或 null