Вопрос по entity-framework, frameworks, c#, entity – Entity Framework всегда включает в себя данные, которые находятся в контексте, даже если я не прошу их

19

Я использую веб-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 я хочу именно то, что я прошу явно. Кажется, что даже с отложенной загрузкой, свойства навигации, которые уже находятся в контексте (то есть обычно "циркулярные ссылки ") будет загружен и возвращен.

with LazyLoading turned off - эммт этонетерпеливая загрузка? Robert Harvey
Вау, так что с отложенной загрузкой вы говорите, что если я выберу одного пользователя без .Включая что-либо, он будет загружать весь график? Какая загрузка мне нужна, когда я просто загружаю то, что мне явно сказано? chris1234p
Просто маленькая хедз-ап. Lazy-loading означает, что он будет загружать только то, что ему нужно, когда это необходимо ... отключение этого является не интуитивным для того, что вы 'ищу. Rick Petersen
У меня та же проблема, что и у @ chris1234p. В моем случае яЯ пытаюсь загрузить список комментариев, и у каждого комментария есть родительский комментарий. Комментарии родителей заполняются (вопреки моим желаниям), и это 'Как будто EF объявил открытый сезон на этом столе, как только я впервые его коснусь. Я не испытываю такой же проблемы с другими отношениями, которых пока нет »в рамках"например, автор. Tyler

Ваш Ответ

5   ответов
-2

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

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 }

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

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

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

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

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

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

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

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

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

что при отложенной загрузке вы вернетесь к свойствам навигации, потому что они "прикоснулся» сериализатором, который заставляет их загружаться. Ленивая загрузка должна быть отключена, если вы хотите, чтобы свойства возвращались как нулевые. Тем не менее, это "кажется» что после загрузки сущностей в контекст (например, с помощью других запросов) они будут обработаны сериализатором. Поэтому ответ заключается в том, чтобы указать сериализатору не возвращать свойства навигации. Лучший способ, которым ямы смогли найти для этого использование 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));
1

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

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

context.Include("Roles")

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

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

Похожие вопросы