LINQ, Null handle in the model

I am trying to pass AverageRating in my opinion. AverageRating is the result of querying elements in the Icollection of the Review model. The review model has the Rating property. However, I get this message:

System.ArgumentNullException

This happens whenever get is executed, which is understandable. However, what is the best way to handle exceptions from scratch in my model or elsewhere when my code looks like this:

public class MyModel
{

        //Querying this navigation property
        public ICollection<Review> Reviews { get; set; }

        public double? AverageRating
        {
        get
        { 
            //check that this is not null / handle null
            return Math.Round(Reviews.Average(c => c.Rating), 1);
        }

        }

}
public class Review
{
    [Key]
    public int ReviewID { get; set; }
    public int Rating { get; set; }
    public string Comment { get; set; }
    public int CoachID { get; set; }
    public int? StudentID { get; set; }


    public Coach Coach { get; set; }
    public Student Student { get; set; }
}
+4
source share
4 answers

This implementation can do what you need:

public double? AverageRating
{
    get
    {
        return Reviews?.Average(x => x?.Rating);
    }
}

He will deal with Reviews null(he will refund null) due to use ?after Reviews.

Reviews, null ( ), - ? x.

+3

null?

, , null unknown. Null Is Not Empty . SQL . null , null int? .

, :

1. nulls

, . ( .NET). , :

public class Model
{
    // is non-null in any Model instance
    public IReadOnlyList<ModelItem> Items { get; }

    public Model(IEnumerable<ModelItem> items)
    {
        Items = new List<ModelItems>(items); // does not check if items contains null
    }
}

2.

null, ( ). , null , null throw.

public class ModelItem
{
    public double? Value { get; set; }
}

public class Model
{
    public ICollection<ModelItem> Items { get; set; } // for some reason, e.g. serialization, the Items collection can be null

    public double? Average
    {
        get
        {
            if (Items == null)
            {
                // I don't know what items exist => the average is unknown
                return null;
            }

            return Items.Average(i => i?.Value); // note the ?. here to prevent NullReferenceException
       }
    }
}

, Average<Nullable<double>> InvalidOperationException , ,

, null - , null. null -, , , - (, , , , null).

, , null ( ), , (??).

+3

DefaultIfEmpty 0 Average, ;

    public double? AverageRating
    {
        get
        {
            if (Reviews == null)
            {
                return null;
            }
            return Math.Round(Reviews.Where(x => x.Rating.HasValue).Select(x => x.Rating).DefaultIfEmpty(0).Average().Value, 1);
        }
    }
+1

# 6.0, , .

:

return Math.Round(Reviews?.Average(c => c.Rating) ?? 0.0, 1);

NULL, , Null Average.

, NULL, :

return Math.Round(Reviews?.Average(c => c?.Rating ?? 0.0) ?? 0.0, 1);

, , , .

, : https://dotnetfiddle.net/qBTEyf

NULL 0, NULL Where.

return Math.Round(Reviews?.Where(c => c?.Rating != null).Average(c => c.Rating) ?? 0.0, 1);

, Average.

In the comments below you can use DefaultIfEmptyto process when the sequence itself is empty, as shown below:

return Math.Round(Reviews?.DefaultIfEmpty().Average(c => c?.Rating ?? 0.0) ?? 0.0, 1);

The call DefaultIfEmptywill return IEnumerableto it there will be one zero element. This will then be filtered out in time Averageand will return 0.

It can also be combined with other methods in this post. The script has been updated with a test use case DefaultIfEmpty.

+1
source

Source: https://habr.com/ru/post/1690523/


All Articles