I'll try and illustrate my question with an oversimplified example: Imagine I have a domain entity like this:
public class Box
{
public int Id { get; set; }
public int Height { get; set; }
public int Width { get; set; }
public int Depth { get; set; }
public int Volume => Height * Width * Depth;
}
Where I'm doing a calculation (volume) based on every other property. Now say I want to store this class using Entity Framework Core. Is there any way I can make EF core store the current value of Volume in its own column when i persist the entity?
That's my core question. I'm not allowed to share my actual code, but here's some more in-depth information about my real-world entity(let's call it "Box"):
Some ideas on how to solve this:
public class Box
{
public int Id { get; set; }
public int Height { get; set; }
public int Width { get; set; }
public int Depth { get; set; }
public int Volume {
get => CalculateVolume();
private set => _volume = value; }
private int _volume;
private int CalculateVolume() => Height * Width * Depth;
}
Which does seem to do what I want, but for some reason feels like cheating, and polluting my domain entity. Also I'm unsure this actually works in all cases, but this is my preferred solution at the time of writing.
I'd prefer to be able to just configure this using fluent API. I noticed the PropertyBuilder.ValueGeneratedOnAdd()-method description says "The value may be generated by a client-side value generator or may be generated by the database as part of saving the entity.", but I can't find any examples of client-side value-generation.
Any and all reasonable feedback welcome.
EDIT: Just to clarify: The actual calculation is pretty complex and uses values from 7 different tables. There's also a weighting of each property involved. The Box example at the start is over simplified and for explanation purposes only. Suffice to say, I need to keep the calculation in my code. I just want to store the result.
Below is the response I got from EF guys for the same problem:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Box>()
.Property(e => e.Volume)
.UsePropertyAccessMode(PropertyAccessMode.Property);
}
or
modelBuilder.UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);
You can use fluent api to compute it on sql server
class MyContext : DbContext
{
public DbSet<Box> Box { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Box>()
.Property(p => p.Volume)
.HasComputedColumnSql("[Height] * [Width] * [Depth]");
}
}