Efcore: Queries swallowing exceptions that should be thrown

Created on 26 Jun 2020  路  4Comments  路  Source: dotnet/efcore

It appears that under certain conditions, EF Core is swallowing LINQ expressions exceptions that should throw. This is unexpected behavior.

Steps to reproduce

``` C#
context.Add(new ConcreteB("01"));
context.Add(new ConcreteB("02"));
context.Add(new ConcreteB("03"));
context.Add(new ConcreteB("04"));
context.Add(new ConcreteB("05"));
context.SaveChanges();

        var count = context.Set<ConcreteB>().Count(p => p.Id.Contains("0")); //count is 5
        var q = from concreteA in context.Set<ConcreteA>()
                select new
                {
                    a = concreteA.Id,
                    b = context.Set<ConcreteB>().Single(p => p.Id.Contains("0")), //Does not throw as expected. This should throw...
                    //c = context.Set<ConcreteB>().Single(), //Throws as expected
                };

        //var query = q.ToQueryString();
        var list = q.ToList();

```
-->

Further technical details

EF Core version: 5.0.0-preview.8.20325.10
Database provider: Microsoft.EntityFrameworkCore.SqlServer 5.0.0-preview.8.20325.3
Target framework: 5.0.0-preview
Operating system: Win10
IDE: Visual Studio 2019 16.3

closed-by-design customer-reported

All 4 comments

Refer to https://github.com/dotnet/efcore/issues/15559

Throwing exception for First/Single/Last (or Default variations) requires to evaluate it on client since database does not throw exception. For a subquery, that behavior is not helpful. Further, in EF6 also Single in a subquery behaved like First only.

Exception throwing can be different for many other scenarios like arithmetic overflow, if database does not have same throwing behavior as C# then you will see difference.

Isn't the behavior inconsistent when:
context.Set<ConcreteB>().Single(p => p.Id.Contains("0")) doesn't throw but context.Set<ConcreteB>().Single() does throw?

Please provide a self-containing runnable repro code.

Actually, context.Set<ConcreteB>().Single() because it is not correlated with query in any form, so it is evaluated on client and converted to a parameter for query even before we start translating the query. Single with predicate has lambda so we did not evaluate it on client before translating the query.

Was this page helpful?
0 / 5 - 0 ratings