markjprice / cs12dotnet8

Repository for the Packt Publishing book titled "C# 12 and .NET 8 - Modern Cross-Platform Development Fundamentals" by Mark J. Price
636 stars 199 forks source link

Pages 556 and 557 - Random number and Global Filter #67

Closed rmantel23 closed 2 months ago

rmantel23 commented 2 months ago

Defining the global filter as described on page 557 will break GetRandomProduct() from page 556 since in that query you select a product by ProductId.

After the filter is active rowCount will change from 77 to 69, but the FirstOrDefault() might now not find anything if the randomly selected ProductId is discontinued.

Get a random product dbug: 9/5/2024 13:30:41.338 RelationalEventId.CommandExecuting[20100] (Microsoft.EntityFrameworkCore.Database.Command) Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30'] SELECT COUNT() FROM "Products" AS "p" WHERE NOT ("p"."Discontinued") dbug: 9/5/2024 13:30:41.340 RelationalEventId.CommandExecuting[20100] (Microsoft.EntityFrameworkCore.Database.Command) Executing DbCommand [Parameters=[@__p_1='69' (Nullable = true)], CommandType='Text', CommandTimeout='30'] SELECT "p"."ProductId", "p"."CategoryId", "p"."UnitPrice", "p"."Discontinued", "p"."ProductName", "p"."UnitsInStock" FROM "Products" AS "p" WHERE NOT ("p"."Discontinued") AND "p"."ProductId" = CAST(abs(random() / 9.2233720368547799E+18) @__p_1 AS INTEGER) LIMIT 1 Fail > Product not found.

Using ElementAt would work

    //Product? p = db.Products?.FirstOrDefault(p => p.ProductId == (int)(EF.Functions.Random() * rowCount));
    Random rnd = new();
    Product? p = db.Products?.ElementAt(rnd.Next(0, (int)rowCount));

but of course, that wouldn't need (or work with) EF.Functions.Random() defeating the purpose.

Maybe you know another way to make the FirstOrDetault() work without needing ProductId (maybe using ROWNUMBER somehow).

markjprice commented 2 months ago

I have written an improvement item for this: https://github.com/markjprice/cs12dotnet8/blob/main/docs/errata/improvements.md#page-556---generating-a-random-number-in-queries