Entity Framework всегда включает в себя данные, которые находятся в контексте, даже если я не прошу их

Я использую веб-API MVC.NET, сначала EF с БД, и в моем контексте отключена отложенная загрузка. EF возвращает слишком много данных, даже если LazyLoading отключен.

Например, у меня есть пользователи с одной ролью. Когда я запрашиваю пользователей и включаю роль, свойство Role.Users автоматически заполняется данными, поскольку пользователи были загружены в контекст.

Почему можноt Я получаю EF, чтобы дать мне ТОЛЬКО то, что я прошу? Или я что-то здесь упускаю?

public partial class User
{
    public int UserID { get; set; }
    public string Title { get; set; }
    public string Email { get; set; }
    public int RoleID { get; set; }

    ....

    public virtual Role Role { get; set; }
} 

public partial class Role
{
    public int RoleID { get; set; }
    public string RoleName { get; set; }

    ....

    public virtual ICollection Users { get; set; }
} 




return db.Users.Include(u => u.Role);
// ^^ user.Role.Users is filled with 1000s of users

TL; DR - я хочу, чтобы EF никогда не загружал данные в свойства / коллекции навигации, если только я .Include () их напрямую. При сериализации в JSON я хочу именно то, что я прошу явно. Кажется, что даже с отложенной загрузкой, свойства навигации, которые уже находятся в контексте (то есть обычно "циркулярные ссылки ") будет загружен и возвращен.

 Judo03 дек. 2012 г., 22:04
Можете ли вы опубликовать код - ваша модель плюс код доступа к данным.
 Robert Harvey03 дек. 2012 г., 21:59
with LazyLoading turned off - эммт этонетерпеливая загрузка?
 Rick Petersen03 дек. 2012 г., 21:59
Просто маленькая хедз-ап. Lazy-loading означает, что он будет загружать только то, что ему нужно, когда это необходимо ... отключение этого является не интуитивным для того, что вы 'ищу.
 Yahia03 дек. 2012 г., 22:25
@ chris1234p нет, ты сказал это не лениться ... быть "не ленивый" означает, что он должен загружаться все сразу, не ожидая, пока это может понадобиться (при первом доступе к коллекции) ... что, в свою очередь, "нетерпеливая загрузка (противоположность "ленивая загрузка ").
 chris1234p03 дек. 2012 г., 22:30
Вау, так что с отложенной загрузкой вы говорите, что если я выберу одного пользователя без .Включая что-либо, он будет загружать весь график? Какая загрузка мне нужна, когда я просто загружаю то, что мне явно сказано?
 Tyler16 дек. 2012 г., 21:34
У меня та же проблема, что и у @ chris1234p. В моем случае яЯ пытаюсь загрузить список комментариев, и у каждого комментария есть родительский комментарий. Комментарии родителей заполняются (вопреки моим желаниям), и это 'Как будто EF объявил открытый сезон на этом столе, как только я впервые его коснусь. Я не испытываю такой же проблемы с другими отношениями, которых пока нет »в рамках"например, автор.
 chris1234p03 дек. 2012 г., 22:05
Из того, что я понимаю и проверял - отложенная загрузка означает, что при доступе к свойству объекта, который является коллекцией, он загружает эту коллекцию. У меня есть, потому что я нея не хочу, чтобы он загружал что-либо, кроме того, что я сказал, чтобы оно было включено Моя проблема в том, что даже если это отключено, оно по-прежнему включает коллекции, которые были загружены в контексте, поэтому у пользователей есть одна роль, а у ролей есть много пользователей в качестве свойства навигации, и он уже загружен тысячами пользователей, хотя я А не было»Скажи EF, чтобы включить его.
 Felix04 дек. 2012 г., 02:37
Нет этоЭто не так, ленивая загрузка будет загружать данные каждый раз, когда вы к ним обращаетесь, когда энергичная загрузка загружает их сразу же, когда вы создаете команду выбора. В любом случае, вы получаете эти данные только потому, что обращаетесь к ним, и если вы не коснетесь этих свойств, EF не загрузит их из БД. Вы должны поиграться с профилировщиком SQL, чтобы посмотреть, когда и какие запросы выполняются.

Ответы на вопрос(5)

Исправление отношений и вы не можете отключить его.

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

return db.Users.Include(u => u.Role).AsNoTracking();

Или используйте проекцию в объект, специализированный для сериализации, как предложено @STLRick.

 chris1234p04 дек. 2012 г., 16:06
По какой-то причине, когда я пытался AsNoTracking, я получал ошибки во время сериализации.
 Slauma04 дек. 2012 г., 16:40
@ chris1234p: Возможно, задайте новый вопрос и опишите эти ошибки. Я сосредоточил внимание на вашем вопросе, как можно избежать заполнения всех свойств навигации между объектами.

Второе: если вы хотите отфильтровать то, что вы извлекаете и возвращаете, сделайте пользовательский объект возврата или что-то еще.

from u in db.Users
join r in db.Roles
  on u.RoleID equals r.RoleID
select new { u.UserID, u.Title, u.Email, r.RoleName }

Или что-то типа того. У вас будет минимальный возвращаемый объект, а ваш граф объектов будет крошечным.

 user184364024 янв. 2013 г., 19:20
при ленивой загрузке вы вернетесь к свойствам навигации, потому что они затронуты сериализатором.

Вы можете выбрать только то, что вам нужно, используя.Select()

var users = _db.Users.Select(x => new
{
    UserID = x.UserID,
    Title = x.Title,
    Email = x.Email,
    RoleID = x.RoleID
}).AsEnumerable();

чтобы он загружал что-либо, кроме того, что я сказал, чтобы оно было включено.

Похоже, вам нужно использоватьЯвная загрузка, По сути, вы можете загрузить конкретные объекты, как это:

context.Include("Roles")

Насколько мне известно, это не должно включать связанные лица. Ленивая загрузка действительно должна быть отключена, и вы можете явно загружать навигационные свойства.Load

 Rick Petersen03 дек. 2012 г., 23:06
Если часть требования заключается в том, чтобы объекты все еще были присоединены к контексту и, следовательно, обновлялись и тому подобное, то это лучшее решение, чем моё ниже. Убедитесь, что вы всегда включаете то, что вам нужно; если вы согласитесь, я согласен с Сержем, это, вероятно, приблизит вас к тому, что вы хотите.
 chris1234p04 дек. 2012 г., 14:55
Здравствуйте, Серж, это то, что я делаю, но похоже, что для того, чтобы это включало только то, что я говорю, мне нужно использовать совершенно новый контекст. В противном случае, если данные уже находятся в контексте, они будут загружены в возвращаемые данные, даже если я непросить об этом. Это как будто он пытаетсяПомогите" меня, давая мне вещи, которые я непросить.

что при отложенной загрузке вы вернетесь к свойствам навигации, потому что они "прикоснулся» сериализатором, который заставляет их загружаться. Ленивая загрузка должна быть отключена, если вы хотите, чтобы свойства возвращались как нулевые. Тем не менее, это "кажется» что после загрузки сущностей в контекст (например, с помощью других запросов) они будут обработаны сериализатором. Поэтому ответ заключается в том, чтобы указать сериализатору не возвращать свойства навигации. Лучший способ, которым ямы смогли найти для этого использование DTO (объектов передачи данных). Это позволяет вам возвращать именно те данные, которые вы хотите, а не ваши фактические сущности.

Ваш DTO может выглядеть примерно так:

public partial class UserDto
{
    public UserDto(user User)
    {
        UserID = user.UserID;
        Title = user.Title;
        //... and so on
    }
    public int UserID { get; set; }
    public string Title { get; set; }
    public string Email { get; set; }
    public int RoleID { get; set; }

    //exclude the Role navigation property from your DTO
}

... и тогда вы могли бы сделать что-то вроде этого:

return db.Users.Include(u => u.Role).Select(user => new UserDto(user));

Ваш ответ на вопрос