2013-12-03 4 views
4

Я работаю с Entity Framework коды первым, и у меня есть класс Course, который имеет свойство навигации Students:Entity Framework: Навигация Свойство Issue

public virtual Collection<Student> Students { get; set;} 

Он работает нормально, но, как я это свойство навигации , все данные извлекаются из базы данных:

var allStudents = course.Students; // Here it retrieves the data 
var activeStudents = allStudents.Where(n => n.Active); // Here it filter the data on memory 
var listOfActiveStudents = activeStudents.ToList(); // It already has the data on memory. 

Как вы можете себе представить, мне нужен запрос, который будет выполнен, когда я делаю .ToList(), потому что я не хочу, чтобы привести все Students из datab ase, только активные.

Знаете ли вы, что я делаю неправильно?

ответ

0

Ленивая загрузка загружает весь набор в память , Если вы не хотите, что переключатель отложенной загрузки от удаления virtual ключевого слова и использовать объект запроса на DbEntry:

public GetCourseWithActiveStudentsLoaded(int courseid) 
{ 
    var course= context.Courses.Find(courseid); 

    context.Entry(course) 
      .Collection(c => c.Students) 
      .Query() 
      .Where(s => s.Active) 
      .Load(); 

    return user 
} 

является «активным» флагом индикатора, который вы пытаетесь осуществить мягкое удаление? Если это так, есть решение здесь: Soft Delete in Entity Framework

Вы можете проголосовать за фильтруется включает здесь: Allow filtering for Include extension method

Другой способ сделать это было бы с наследованием. Вы могли бы иметь ActiveStudent наследующий Student и свойство ActiveStudents навигации, а как свойство AllStudents навигации в Course классе

public virtual Collection<Student> AllStudents { get; set;} 
public virtual Collection<ActiveStudent> ActiveStudents { get; set;} 

Ссылка:

Applying filters when explicitly loading related entities:

+0

, каков тип 'user.Students', что он имеет метод' .Query() '? – Moho

+0

«Активное» поле является примером. Я должен применять более сложные фильтры. Я попытался удалить «виртуальный», и он не запускает запрос ... но он ничего не приносит, когда выполняется «ToList()» (он не выполняет никаких запросов) –

+0

@Moho ах. Мой плохой ;-(Я нахожусь на неправильном уровне здесь. Мне нужно 'DbCollectionEntry'. – Colin

3

Если бы вы использовали правильное печатание переменных, вы бы увидели, что происходит. Свойство загрузки полностью загружено в память с помощью свойства навигации.

//user is an instance of the class User referenced by DbSet<User> 
//when you lazy load a navigation property in that set, it loads the data 
ICollection<Student> allStudents = user.Students; 

//At this point, all of the data was lazy loaded 
//But the Where creates an IEnumerable of the in memory set 
IEnumerable<Student> activeStudents = allStudents.Where(n => n.Active); 

//At this point, the IEnumerable is iterated, and a List is returned 
List<Student> listOfActiveStudents = activeStudents.ToList(); 
+0

Спасибо, я знаю, что ... проблема заключается в том, что ученики извлекаются в первой строке при доступе к навигационному свойству. Как я могу сделать для получения только активных учеников? –

+0

Я имею в виду ... запрос выполняется в первой строке, а затем применяется фильтр в памяти. Но я хочу, чтобы запрос выполнялся, когда я делаю «ToList()» –

+1

@ArielScherman. Для этого вам нужно «IQueryable». Вы должны отправить запрос в таблицу учеников с использованием отношения внешнего ключа. Что-то вроде 'db.Students.Where (s => s.Active && s.UserId == user.UserId)'. Это даст вам «IQueryable», способный использовать отложенное выполнение, которое вы ищете. –

2

использование dbContext.Entry(user).Collection(u => u.Students).Query() получить IQueryable<Student> для навигации собственности студентов коллекции, в какой момент вы можете добавить свой фильтр и перечислять каждый раз, когда вы будете готовы к данным

+2

Итак ..не существует решения для навигационных свойств? Как это возможно? Я работаю с шаблоном репозитория, поэтому делать то, что вы говорите, является болью в заднице. –

+1

Lazy loading navigation properties - это операция «все или ничего», которая по существу является «dbContext.Entry (user) .Collection (u => u.Students) .load() '. Используя '.Query()', вы можете фильтровать результаты до их загрузки из БД. Я бы подумал, что шаблон репо сделает это менее громоздким, поскольку вы уже абстрагируете загрузку объектов от разработчика – Moho

Смежные вопросы