Как фильтровать IQueryable для нулевого свойства навигацииC#

Место общения программистов C#
Ответить
Anonymous
 Как фильтровать IQueryable для нулевого свойства навигации

Сообщение Anonymous »

Предположим, у меня есть две простые модели (ниже), где «Пользователь» содержит свойство навигации для «UserDetail» (отношения «один к одному»):
База данных

Код: Выделить всё

CREATE TABLE [dbo].[UserDetail]
(
[UserId] [int] NOT NULL PRIMARY KEY,
[Name] varchar(100) NULL
)
CREATE TABLE [dbo].[User]
(
[UserId] [int] NOT NULL PRIMARY KEY
)
C#.NET

Код: Выделить всё

[Table("UserDetail"), Schema="dbo"]
public class UserDetail
{
[Key, Required, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int UserId { get; set; }
public string Name { get; set; }
// Additional Properties Not Listed
}

[Table("User"), Schema="dbo"]
public class User
{
[Key, Required]
public int UserId { get; set; }
// Additional Properties Not Listed

[ForeignKey("UserId")]
public virtual UserDetail UserDetail { get; set; }
}
Теперь приложение .NET использует архитектуру репозитория, поэтому я сначала настраиваю запрос к таблице «Пользователь» (поведение Entity Framework по умолчанию; отложенная загрузка):< /p>

Код: Выделить всё

IQueryable users = DataRepository.UserRepository.List(); // 'List()' returns an IQueryable
Моя конечная цель — просто добавить фильтр, который будет извлекать только «Пользователей», у которых НЕТ связанной записи «UserDetail» (т. е. свойство навигации будет иметь значение NULL). :

Код: Выделить всё

users = users.Where(m => m.UserDetail == null); // Also tried (m => m.UserDetail.Equals(null))
var testing = users.ToList();
Но при проверке переменной «тестирование» запрос ВСЕГДА возвращает пустое значение (в базе данных есть записи «Пользователь» со связанными «UserDetails» и без них). После некоторых первоначальных исследований выяснилось, что это потенциально связано с ленивой загрузкой. Чтобы проверить, я попробовал следующий пример:

Код: Выделить всё

users = users.Where(m => m.UserDetail.Name == "UserName");
var testing = users.ToList();
К моему удивлению, это сработало так, как и ожидалось; переменная «тестирование» содержала записи «Пользователь», с которыми была связана запись «UserDetail» со ​​свойством «Имя», равным «Имя пользователя». Теперь кажется, что отложенная загрузка - это не проблема, а скорее потенциальная проблема с IQueryable, сравнивающим NULL-свойства навигации (во время трансляции SQL-запроса?).
В окончательном тесте решено попробовать использовать метод Include и посмотреть, имеет ли это значение, но он дал тот же результат, что и первый тест (т. е. пустой):

Код: Выделить всё

users = users.Include(m => m.UserDetail).Where(m => m.UserDetail == null);
var testing = users.ToList();
Итак, я сейчас в растерянности и, очевидно, недостаточно хорошо понимаю, чтобы добиться желаемых результатов. Буду рад любому совету/помощи от всех, кто знает, где я столкнулся с этой проблемой.
Я думаю, что запрос IQueryable переводит свойства навигации как 'JOIN'(s) а не 'LEFT JOIN'(ы) и, следовательно, не может использоваться для сравнения пустых/нулевых связанных записей (записей просто нет).
Подводя итог вопросам:
  • Как написать запрос в .NET/Entity Framework, который будет выполняться в базе данных, чтобы извлекать только «Пользователей», у которых нет связанной записи «UserDetail» ?
  • Почему IQueryable не извлекает записи, которые я ожидал в своем первом тесте?
  • Уточните все общие моменты, которые я упускаю в отношении функциональности IQueryable.
Заранее благодарим за любую помощь/совет!

Подробнее здесь: https://stackoverflow.com/questions/720 ... n-property
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»