Entity Framework не может получить указанную c запись по ее идентификатору в C# бэкэнде - PullRequest
0 голосов
/ 09 января 2020

Допустим, у меня есть таблица с именем Books, у меня есть несколько записей в ней, как показано ниже

ID    BookName
1      Book1
2      Book2
3      Book3

, когда я запрашиваю таблицу выше из моего C# бэкэнда, используя идентификатор записи, как показано ниже

var result = context.Books.where(b => b.ID == 1).FistOrDefault();

Я получаю нулевое значение для ID = 1, но для идентификаторов 2,3 я получаю целые записи. Когда я напрямую запрашиваю идентификатор записи = 1 в SSMS, я получаю идентификатор записи 1. Это не имеет смысла для меня, почему и как это может произойти. Любая помощь или подсказка будут высоко оценены.

Ответы [ 2 ]

3 голосов
/ 09 января 2020

вам нужно запросить таблицы книг. Пожалуйста, измените ваш запрос, как показано ниже:

var result = context.Books.Where(b => b.ID == 1).FistOrDefault();

или

var result = context.Books.FistOrDefault(b => b.ID == 1);

Кроме того, если он работает со значениями идентификаторов 2 и 3, то в следующий раз я бы хотел проверить, является ли база данных вашей C# на самом деле указывает на. Также я бы проверил схему, где существует таблица книг. По умолчанию EF, таблица запросов, которая имеет схему dbo, если вы не определили иначе.

Следующее, что я хотел бы проверить, это запрос, который отправляется в базу данных. Для этого извлеките context.Books.Where(b => b.ID == 1) в переменную и получите запрос sql и запустите его вручную в SSMS.

var queryableBooks = context.Books.Where (b => b.ID == 1); var result = queryableBooks.FirstOrDefault (); // здесь есть точка останова

Затем во время отладки проверьте queryableBooks SQL через Quick Watch. Вы увидите что-то вроде ниже:

enter image description here

0 голосов
/ 10 января 2020

В качестве альтернативы, запустите трассировку для базы данных, чтобы зафиксировать операторы SQL, фактически выполняющиеся с ней, используйте точку останова в коде, запустите трассировку и выполните строку чтения. Трассировка покажет точные операторы SQL, которые выполняются. Затем вы можете скопировать эти заявления в SSMS, чтобы проверить, что они возвращают. Простым инструментом трассировки, который я использую для SQL Server, является ExpressProfiler, созданный еще в те дни, когда была включена трассировка для SQL Server Express. Хотя я рекомендую собирать его из исходного кода (https://github.com/ststeiger/ExpressProfiler), а не из любого установщика, такого как Sourceforge. SSMS имеет профилировщик в Tools / SQL Server Profiler, который по умолчанию захватывает намного больше шума. Любой инструмент имеет неоценимое значение для исследования как странности EF, так и производительности.

, если context.Books.Where(b => b.ID == 1).SingleOrDefault() возвращает #null, я бы посмотрел, что SQL будет зафиксировано для этого оператора в вашей базе данных. Сравните это с b => b.ID == 2.

Если ваша трассировка ничего не захватывает ни для 1, ни для 2, но вы видите результирующие данные для сценария ID = 2, тогда объяснение будет состоять в том, что ваш DbContext не указывает на базу данных / сервер, о которой вы думаете, или что-то не так с вашей настройкой DbContext.

Если ваша трассировка захватывает что-то для 1 и 2, но вы видите данные только для # 2, проверьте, что запрос для # 1 выполняется и возвращает данные. Если запрос выглядит корректным, но ваш код ничего не видит для идентификатора №1, то каким-то образом ваш DbContext находится в состоянии, когда идентификатор №1 удален. Я бы добавил код, чтобы проверить ChangeTracker DbContext, чтобы выяснить, есть ли запись для # 1, которая находится в состоянии сущности Removed. Возможно, у вас запущен код, неожиданно каскадный для удаления, но SaveChanges не был вызван или не был успешным. Длительно работающие экземпляры DbContext подвержены такого рода проблемам.

Проверьте следующее:

вместо

var result = context.Books.where(b => b.ID == 1).FirstOrDefault(); 

используйте это:

using(var testContext = new MyDbContext())
{
    var result = testContext.Books.where(b => b.ID == 1).SingleOrDefault(); 
}

Подставляя MyDbContext в ваше приложение DbContext. Это устраняет любые забавные дела с длительным состоянием DbContext. Контекст все еще может выполнять SQL, но возвращать то, что находится в кэшированном состоянии.

Примечание. При запросе данных выберите SingleOrDefault вместо FirstOrDefault, если ожидаете результаты 0..1. Операции типа First должны использоваться только в том случае, если вы ожидаете 0..много, но заботитесь только о первом результате, и их всегда следует использовать с условием Order By, чтобы обеспечить предсказуемое упорядочение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...