DbSet.ToList () отбирает другой dbset - PullRequest
0 голосов
/ 08 мая 2018

Я использую Entity Framework в своем приложении, и у меня есть модели «один ко многим», подобные этой:

public class Email
{
    public string Id { get; set; }
    public string To { get; set; }
    public string From { get; set; }
    public string CC { get; set; }
    public string Bcc { get; set; }

    public string Subject { get; set; }
    public string Body { get; set; }

    public ICollection<AnexoEmail> Anexos{get;set;}
}

public class AnexoEmail
{
    [Key]
    public string Id { get; set; }

    /// <summary>
    /// Full path do ficheiro
    /// </summary>
    public string Nome { get; set; }
    public DateTime DataEnvio { get; set; }
    public bool Enviado { get; set; }

    public string EmailId { get; set; }
    public Email Email { get; set; }
}

Представляет собой отношение Email-Attachment. Дело в том, что у меня есть UOW и репозиторий EmailRepository, и происходит нечто, чего я не могу понять: В хранилище:

public class EmailRepository : IEmailRepository
{
    internal DbContext _context;
    internal DbSet<Email> dbSet;
    internal DbSet<AnexoEmail> dbSetAnexo;

    public EmailRepository(DbContext context)
    {
        _context = context;
        dbSet = context.Set<Email>();
        dbSetAnexo = context.Set<AnexoEmail>();
    }
    (...)
    public IEnumerable<Email> GetAll()
    {
        dbSetAnexo.ToList(); //<- I can´t understand this part

        var emails = dbSet.ToList();
        return email;
    }
}

В этом примере я ожидаю, что emails.Anexos будет null, но по какой-то причине, если я добавлю эту строку, emails.Anexos получит правильные вложения (anexos), а если я не emails.Anexos будет нулевым, как и ожидалось.

У меня нет большого опыта работы с ядром Ef, если я пропускаю какой-то класс или что-нибудь, просто скажите мне.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Все это вызвано отслеживанием объекта . Строка dbSetAnexo.ToList(); заставляет Entity Framework отслеживать всего DbSet, вы можете думать об этом как о форме кэширования, если хотите. Так как EF «кэшировал» эти AnexoEmail объекты, он представит их вам, когда вы запросите значение email.Anexos.

Вы можете предотвратить это, используя метод расширения AsNoTracking(), например:

dbSetAnexo.AsNoTracking().ToList();

Теперь вместо этого вы должны использовать функцию Include, которая заставит EF загрузить указанных связанных потомков . Например:

var emails = dbSet
    .Include(e => e.Anexos)
    .ToList();
0 голосов
/ 08 мая 2018

Это связано с тем, что на самом деле делает .ToList(). Он не меняет первоначальное значение коллекции, он просто создает новый List<> и возвращает его. То, что вы сейчас делаете, это выбрасывает значение в окно и ничего не делает с ним. Есть два способа его хранения:

DbSet<AnexoEmail> dbSetAnexo;     // Keep original DbSet<>
List<AnexoEmail> listAnexo;       // Make new List<AnexoEmail>

listAnexo = dbSetAnexo.ToList();

Тогда вы бы использовали listAnexo вместо dbSetAnexo. Если вам это не нравится и вы хотите использовать только одну переменную, вы можете использовать тип dynamic, который является единственным типом, который может меняться от одного типа к другому во время выполнения.

dynamic anexoEmails = new DbSet<AnexoEmail>();    // anexoEmails is currently a dBSet<>
anexoEmails = anexoEmails.ToList();               // anexoEmails is now a List<>

Последний может вести себя так, как вы ожидали. Просто имейте в виду, что с типами dynamic вы не будете получать столько проверок компилятора и никакого автозаполнения IDE, сколько все это проверяется во время выполнения.

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