Почему иногда выдает запрос непустая последовательность, чья единственная строка имеет PK 0? - PullRequest
0 голосов
/ 09 января 2020

Рассмотрим эту простую модель:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace ConsoleApp3
{
    public class ApplicationDbContext : DbContext
    {
        public DbSet<WTF> Wtf { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder options)
            => options.UseSqlServer("Server = (localdb)\\mssqllocaldb; Database=DAFAQ0001;Trusted_Connection=True;");
    }

    public class WTF
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None), Key] public long Aargh { get; set; }

        public override string ToString() => Aargh.ToString();
    }
}

Давайте попробуем поместить одну строку в созданную таким образом таблицу и затем запросить эту единственную строку:

using System;
using System.Linq;

namespace ConsoleApp3
{
    class Program
    {
        static void Main()
        {
            var db = new ApplicationDbContext();

            db.Wtf.Add(new WTF { Aargh = 0 });
            db.SaveChanges();

            Console.WriteLine(db.Wtf.Any()); // TRUE
            Console.WriteLine(db.Wtf.First().ToString()); // WORKS

            Console.WriteLine(db.Wtf.Max(wtf => wtf.Aargh)); // EXCEPTION
        }
    }
}

Да - последняя Линия производит большое, толстое, безобразное исключение. Очевидно, sequence contains no elements, что кажется странным, потому что он содержит один элемент, который я только что вставил! И сам метод Any подтверждает это. Еще хуже - запрос этого единственного элемента также работает, что подтверждается вызовом First. Это просто Max, который терпит неудачу, по причинам, которые я не могу понять.

True
0
Unhandled exception. System.InvalidOperationException: Sequence contains no elements.
   at lambda_method(Closure , QueryContext , DbDataReader , ResultContext , Int32[] , ResultCoordinator )
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.Max[TSource,TResult](IQueryable`1 source, Expression`1 selector)
   at ConsoleApp3.Program.Main() in C:\Users\m\source\repos\ConsoleApp3\ConsoleApp3\Program.cs:line 23

C:\Users\m\source\repos\ConsoleApp3\ConsoleApp3\bin\Debug\netcoreapp3.1\ConsoleApp3.exe (process 11432) exited with code -532462766.
Press any key to close this window . . .

Как ни странно, вставка этого единственного элемента с PK 1 вместо 0, кажется, решает проблему.

Что здесь происходит? Является ли 0 недопустимым значением для первичного ключа? Я гуглил и нашел этот SO-ответ: SQL первичный ключ может принимать '0'? , что говорит о том, что 0 является совершенно допустимым значением первичного ключа!

Может кто-нибудь объяснить, почему не работает ли приведенный выше код?

Редактировать: Отвечать на комментарии: Если я щелкаю в VS окно SQL Server Explorer и вижу код этой таблицы, это то, что я получаю:

CREATE TABLE [dbo].[Wtf] (
    [Aargh] BIGINT NOT NULL,
    CONSTRAINT [PK_Wtf] PRIMARY KEY CLUSTERED ([Aargh] ASC)
);

Профилирование этого сценария в VS показывает, что SQL выполняется для получения Max:

SELECT MAX([w].[Aargh]) FROM [Wtf] AS [w]

Выполнение этого же запроса SQL в Sql Обозреватель объектов сервера в VS создает следующие результаты:

(No column name)
0
...