【发布时间】:2019-09-20 20:51:52
【问题描述】:
我有一个简单的一对多关系。 家长:
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。之后它查询事务,当它们被加载时,客户的事务从 null 变为 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)");
}
}
【问题讨论】:
-
这是正常行为。 Relationship fix-up.
-
@Gert Arnold,那我该怎么处理呢?确保 .AsNoTracking()。我认为这不是一个好的解决方案(它解决了问题,但如果我想 SaveChanges()?)。我不想让一些单独的查询影响我之前的查询。
-
为什么要处理它?有什么问题?
-
使用短暂的上下文,或者只为不希望填充其他导航属性的代码段创建一个新的上下文。
标签: entity-framework asp.net-core eager-loading