[英]Update owned entity EF Core 5
I am implementing an api using .net 5. I have a student class which have a property with address type(value object according to ddd).
public class Student
{
public long Id{ get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public Address Address { get; private set; }
}
public class Address
{
public string City { get; private set; }
public string Road { get; private set; }
}
我正在使用流利的 api 使用 ef core 5 配置數據庫。
class StudentConfiguration : IEntityTypeConfiguration<Student>
{
public void Configure(EntityTypeBuilder<Student> builder)
{
builder.ToTable("Students");
builder.HasKey(x => x.Id);
builder.Property(x => x.Id).ValueGeneratedNever().IsRequired();
builder.Property(x => x.FirstName).HasMaxLength(25).IsRequired();
builder.Property(x => x.LastName).HasMaxLength(50).IsRequired();
builder.OwnsOne(x => x.Address, x =>
{
x.Property(pp => pp.City)
.IsRequired()
.HasColumnName("City")
.HasMaxLength(20);
x.Property(pp => pp.Road)
.IsRequired()
.HasColumnName("Road")
.HasMaxLength(40);
});
}
}
結果,我有一個包含 Id、Fistname、lastname、city、road 列的表。
現在我試圖只更新城市和道路(例如學生更衣室),但我有不同的例外,我不知道如何只更新這 2 列
public async Task UpdateAddress(Student student)
{
//Firts try
//var studentEntry = context.Entry(student);
//studentEntry.Property(x => x.Address.City).IsModified = true;
//studentEntry.Property(x => x.Address.Road).IsModified = true;
//**Exception** 'The expression 'x => x.Address.City' is not a valid member access expression. The expression should represent a simple property or field access: 't => t.MyProperty'. (Parameter 'memberAccessExpression')'
//Second try
//var studentEntry = context.Entry(student.Address);
//studentEntry.Property(x => x.City).IsModified = true;
//studentEntry.Property(x => x.Road).IsModified = true;
//**Exception** 'Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded.
//the only method that works is Update but this update the whole object
context.Update(student);
await context.SaveChangesAsync();
}
編輯
public class StudentDbContext : DbContext
{
public DbSet<Student> Students { get; set; }
public StudentDbContext(DbContextOptions<StudentDbContext> options) : base(options)
{
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
base.OnModelCreating(modelBuilder);
}
}
如何只更新擁有實體的這兩個屬性?
Address
是擁有的實體類型,因此 EF Core 術語中的Student.Address
屬性不是屬性,而是引用導航屬性,因此應該通過Reference
方法而不是Property
方法訪問(它們都不支持屬性路徑)。 然后您可以使用返回的跟蹤條目來訪問其成員。
要強制更新Student.Address
的某些屬性,首先附加Student
實體實例(告訴 EF 它存在)
var studentEntry = context.Attach(student);
然后使用這樣的東西
var addressEntry = studentEntry.Reference(e => e.Address);
addressEntry.TargetEntry.Property(e => e.City).IsModified = true;
addressEntry.TargetEntry.Property(e => e.Road).IsModified = true;
由於 EntityFramework 不跟蹤您的查詢(因為您在 DBContext 配置中設置了它),您可以嘗試以下流程:
首先通過其 ID 從 DB 獲取學生,然后僅更改您想直接在該實體上更改的那兩個屬性。
public async Task UpdateAddress(Student student)
{
// Get existing student by its ID from the database
var existingStudent = await context.Students
.Include(x => x.Address)
.SingleOrDefaultAsync(x => x.Id == student.Id);
// To prevent null reference exception
if (existingStudent is null)
return; // Exception maybe? Depends on your app flow
// Edit address value object with the method available in your entity, since you're using DDD approach
existingStudent.ChangeAddress(student.Address);
// Since your query are not tracked you need to explicity tell EF that this entry is being modified
context.Entry(existingStudent).State = EntityState.Modified;
// EF will save only two properties in that case
await context.SaveChangesAsync();
}
在您的Student
實體 class 中添加以下方法以提供更改其地址的能力:
public void ChangeAddress(Address newAddress)
{
// Some additional conditions to check the newAddress for nulls, valid values, etc.
Address = newAddress;
}
您可以將您的地址視為一個值對象並將其替換為新的地址 VO。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.