Почему EF Core загружает дочерние объекты, когда я запрашиваю его без .Include () - PullRequest
0 голосов
/ 20 сентября 2019

У меня простые отношения «один ко многим».Родитель:

public class Customer
    {
        public Customer(string name, string email)
        {
            Name = name;
            Email = email;
        }

        public Customer(string name, string email, long mobile)
            : this(name, email)
        {
            Mobile = mobile;
        }

        //for EF
        private Customer() { }

        public int Id { get; private set; }
        public string Name { get; private set; }
        public string Email { get; private set; }
        public long? Mobile { get; private set; }
        public List<Transaction> Transactions { get; private set; }

        public void AddTransactions(IEnumerable<Transaction> transactions)
        {
            if(Transactions == null)
                Transactions = new List<Transaction>();

            Transactions.AddRange(transactions);
        }
    }

Дочерний объект:

public class Transaction
    {
        public Transaction(DateTimeOffset date, decimal amount, Currency currency, Status status)
        {
            TransactionDate = date;
            Amount = amount;
            CurrencyCode = currency;
            Status = status;
        }

        //for EF
        private Transaction() { }
        public int Id { get; private set; }
        public DateTimeOffset TransactionDate { get; private set; }
        public decimal Amount { get; private set; }
        public Currency CurrencyCode { get; private set; }
        public Status Status { get; private set; }
        public int CustomerId { get; set; }
        public Customer Customer { get; private set; }
    }

Существует простой метод, который запрашивает одного клиента и вызывает для него SingleOrDefault.После этого он запрашивает транзакции, и когда они загружаются, транзакции Клиента изменяются с нуля на Count = 5 (транзакции, которые я загрузил).Почему?В конфигурации я не указал .UseLazyLoadingProxies ().

var customerQuery = _dbContext.Customers.AsQueryable();

            if (!string.IsNullOrEmpty(request.Email))
                customerQuery = customerQuery.Where(c => c.Email == request.Email);

            if (request.CustomerId.HasValue)
                customerQuery = customerQuery.Where(c => c.Id == request.CustomerId.Value);

            var customer = await customerQuery.SingleOrDefaultAsync(cancellationToken)
                .ConfigureAwait(false);
//here customer has null collection of transactions
            if (customer == null)
                throw new NotFoundException("Not Found.");

            var transactions = await _dbContext.Transactions
                .Where(t => t.CustomerId == customer.Id)
                .OrderByDescending(t => t.TransactionDate)
                .Take(5)
                .ToListAsync(cancellationToken);

//here customer has 5 transactions.
            customer.AddTransactions(transactions);
//here it has 10, because of method (following the DDD, it is used for providing business invariant)

EF конфигурация:

 public class CustomerEntityConfiguration : IEntityTypeConfiguration<Customer>
    {
        public void Configure(EntityTypeBuilder<Customer> builder)
        {
            builder.Property(c => c.Id)
                .HasMaxLength(10);

            builder.Property(c => c.Email)
                .HasMaxLength(25)
                .IsRequired();

            builder.Property(c => c.Mobile)
                .HasMaxLength(10);

            builder.Property(c => c.Name)
                .HasMaxLength(30)
                .IsRequired();

            //uniqueness constraint
            builder.HasIndex(c => c.Email)
                .IsUnique();

            builder.HasMany(t => t.Transactions)
                .WithOne(t => t.Customer)
                .HasForeignKey(t => t.CustomerId);
        }

////////////////////////////
public class TransactionEntityConfiguration : IEntityTypeConfiguration<Transaction>
    {
        public void Configure(EntityTypeBuilder<Transaction> builder)
        {
            builder.Property(t => t.Amount)
                .HasColumnType("decimal(10, 2)");
        }
    }

1 Ответ

0 голосов
/ 21 сентября 2019

Это нормальное поведение и следствие долгоживущих DbContexts.Возможно, объясните, почему это поведение нежелательно?

Вариант 1: используйте AsNoTracking ().Это говорит EF не связывать загруженные экземпляры с DbContext.Автосоединение не произойдет.

Вариант 2: Используйте более короткие DbContexts.Уровень модуля DbContexts может быть доступен несколькими способами.Использование более коротких DbContexts, связанных в using блоках, означает, что вызовам не нужно беспокоиться о совместном использовании ссылок.

...