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; }
}
I am using fluent api to configure the database using 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);
});
}
}
As a result I have one table with columns Id,Fistname,lastname,city,road.
Now I am trying to update only the city and the road(for example a student change house) but I have different exceptions and I don't know how to update only these 2 columns
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();
}
EDIT
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);
}
}
How can update only these two properties of an owned entity?
Address
is owned entity type, hence Student.Address
property by EF Core terminology is not a property, but reference navigation property, thus should be accessed via Reference
method rather than Property
method (none of them supports property path). Then you can use the returned tracking entry to access its members.
To force updating just some properties of the Student.Address
, first attach the Student
entity instance (to tell EF that it is existing)
var studentEntry = context.Attach(student);
and then use something like this
var addressEntry = studentEntry.Reference(e => e.Address);
addressEntry.TargetEntry.Property(e => e.City).IsModified = true;
addressEntry.TargetEntry.Property(e => e.Road).IsModified = true;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With