-1

When I run the following Linq:

var selectedProduct = db.Products.FirstOrDefault(a => a.ProductNr == productNr)?.Id;
model.PackTypes = db.Zones
                    .Where(az => az.ProductId == selectedProduct && az.StoragePrio > 0)
                    .ToList()
                    .DistinctBy(p => p.PackType)
                    .OrderBy(x => x.PackType)
                    .Select(x => new DropdownItemViewModel<int>
                                 {
                                     Id = (int)x.PackType,
                                     Name = x.PackType.Translate()
                                 });
return true;

I get this error:

System.InvalidOperationException: 'Nullable object must have a value.' on this code Id = (int)x.PackType,

Now I know I must do a nullcheck so I have tried this:

if (x.PackType != null)
    return new DropdownItemViewModel<int>
    {
        Id = (int)x.PackType,
        Name = x.PackType.Translate()
    };
return null;

Still doesn't work, by that I mean I still have problem with NullCheck.

Lidprogsky
  • 43
  • 8
  • 1
    Models.... please. – ProgrammingLlama Aug 09 '21 at 14:23
  • 1
    Can `az.ProductId` be `null` at some point? If not, why are you doing that query at all vs just exiting early if `selectedProduct == null`? – ProgrammingLlama Aug 09 '21 at 14:25
  • I do a Nullcheck in my model, so I thought I didn't need to share it. – Lidprogsky Aug 09 '21 at 14:25
  • 5
    Why are you calling ToList in the middle of building the chained deferred methods query? What is PackType type? Does it can be converted to an integer using a simple cast? –  Aug 09 '21 at 14:26
  • Does this answer your question? [Casting object to int throws InvalidCastException in C#](https://stackoverflow.com/questions/39891504/casting-object-to-int-throws-invalidcastexception-in-c-sharp) and [How to convert C# nullable int to int](https://stackoverflow.com/questions/5995317/how-to-convert-c-sharp-nullable-int-to-int) and [Invalid cast from 'System.Int32' to Nullable](https://stackoverflow.com/questions/18015425/invalid-cast-from-system-int32-to-system-nullable1system-int32-mscorlib) –  Aug 09 '21 at 14:29
  • 2
    It seems like you want `.Where(az => az.ProductId == selectedProduct && az.StoragePrio > 0 && az.PackType != null)` to filter out any entries where `az.PackType == null`. Unless there's something else that is null here? – ProgrammingLlama Aug 09 '21 at 14:29
  • Either exclude `null` PackTypes in the where clause `.Where(az => az.ProductId == selectedProduct && az.StoragePrio > 0 && az.PackType != null)` or convert nulls to another value `Id = x.PackType ?? 0` – Olivier Jacot-Descombes Aug 09 '21 at 14:31
  • 3
    If you want to force Linq-To-Objects after the `Where` don't use `ToList` but `AsEnumerable`. On that way you don't load all into memory at once but you can use deferred execution. – Tim Schmelter Aug 09 '21 at 14:31

1 Answers1

2

This query more effective and should not have all mentioned errors:

var query = 
    from p in db.Products
    where p.ProductNr == productNr
    join az in db.Zones on p.Id equals az.ProductId
    where az.StoragePrio > 0 && az.PackType != null
    select new { az.PackType };

model.PackTypes = query
    .Distinct()
    .OrderBy(x => x.PackType)
    .Select(x => new DropdownItemViewModel<int>
    {
        Id = (int)x.PackType,
        Name = x.PackType.Translate()
    })
    .ToList();

Instead of two database requests this query sends only one. Also all operations are done on the server side.

Svyatoslav Danyliv
  • 21,911
  • 3
  • 16
  • 32