dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.73k stars 3.18k forks source link

DbUpdateException.Entries is empty when parameter doesn't have valid geography data #22181

Closed brunokc closed 4 years ago

brunokc commented 4 years ago

I'm ingesting data from an XML file into a SQL Server database using EF Core 3.1. I'm using the NetTopologySuite package to add support for geography/geometry types. While ingesting 19,000+ rows, SaveChangesAsync() throws a DbUpdateException exception, which wraps a SqlException with the following message:

'The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 18 ("@p1808"): The supplied value is not a valid instance of data type geography. Check the source data for invalid values. An example of an invalid value is data of numeric type with scale greater than precision.' (Error number 8023)

The exception doesn't help much because the Entries property is empty, so I can't really determine why the SaveChanges() call is not working.

Steps to reproduce

Don't have one at the moment because I can't determine what's wrong with the update -- that's exactly where DbUpdateException.Entries would come in handy. Catch 22.

I'll reduce my dataset to see if I can isolate the instance that's causing this issue.

Further technical details

EF Core version: 3.1 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: NET Core 3.1 Operating system: Windows 10 2004 IDE: Visual Studio 2019 16.6.5

ajcvickers commented 4 years ago

@brunokc Switching off batching in SaveChanges may help you isolate the specific case that is failing. For example:

    .UseSqlServer(_connectionString, b => b.MaxBatchSize(1));
ajcvickers commented 4 years ago

@brunokc Also, this may be fixed in the EF Core 5.0 previews or NTS 2.1. Can you try with those and see if the issue is still reproducable?

ajcvickers commented 4 years ago

Empty entries issue is tracked by #7829

brunokc commented 4 years ago

Thank you, @ajcvickers. As it turns out, I'm already using NTS 2.1. I'll have to try EF Core 5.0 preview at some point.

As for the use of MaxBatchSize, it didn't quite do what I needed -- I was still calling AddRangeAsync() with all entries, which was just slowing things down to a single INSERT at a time (instead of doing multiple MERGEs). Upon encountering the bad entry, it would still fail the same way, still leaving DbUpdateException.Entries empty, making it really hard to see what the problem was. I had to change the code to do a single Add() + SaveChanges() at a time in order to isolate the problem (the problem was that I was representing an empty Point as POINT(NaN NaN 0), which is invalid -- an empty Point doesn't have any coordinates). However, that makes the code significantly slower (regular AddRange() + SaveChanges() takes 22sec already -- I wasn't patient enough to wait for it to finish when using individual calls to Add() + SaveChanges() as it took several minutes to process just bout 5% of the rows)

Having a fix for issue #7829 would be great so people won't have to significantly slow down their code in order to debug such issues. I'll see if I can give EF Core 5.0 preview a try to see if that's fixed there.

Thanks again!

ajcvickers commented 4 years ago

@brunokc The point was to make each INSERT happen in it's own round-trip so you can see from the logs which values are causing the issue. Make sure to turn on EnableSensitiveDataLogging to see the actual values.

brunokc commented 4 years ago

Ah, thank you, @ajcvickers. It makes sense now. I wasn't aware of the EnableSensitiveDataLogging option (somewhat new to all this). Thanks!

AndriySvyryd commented 4 years ago

Fixed in https://github.com/dotnet/efcore/commit/bff57f9e6c30bb00028213b830e8938969bd13a8