Insert default value with shadow property not working as expected
Was hoping to use HasDefaultValue to insert some default value to db without adding it to our entity.
But it seems not working and we need to set the current value before save.
Here is some sample code
```c#
public class Account
{
public int Id { get; set; }
}
public class SqlDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(@"Server=.;Database=local;Trusted_Connection=True;");
protected override void OnModelCreating(ModelBuilder builder) =>
builder.Entity<Account>(m =>
{
m.ToTable("users", "dbo");
m.HasKey(x => x.Id);
m.Property(x => x.Id).HasColumnName("id");
// Shadow properties
m.Property<string>("some_out_of_domain_column")
.HasDefaultValue("some_out_of_domain_data");
});
}
public class Program
{
public static async Task Main()
{
using (var context = new SqlDbContext())
{
var account = new Account();
var entry = context.Add(account);
// This is what we finally did
//entry.Property("some_out_of_domain_column").CurrentValue = "some_out_of_domain_data";
await context.SaveChangesAsync(CancellationToken.None);
}
}
}
```
EF Core version: 2.1.4
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10
IDE: Visual Studio 2017 15.8.5
@jasonycw HasDefaultValue is for specifying the default value to configure as a constraint on the column in the database, which can then be applied using migrations. If you are mapping this to an existing column, then it won't have any affect. Having the ability to set a client-side default may be a useful addition--we will discuss. For now, setting it in SaveChanges seems like a good workaround.
@divega to find dupe
@ajcvickers to try a value generator
Duplicate of #11001
@jasonycw It was pointed out that this can actually be done today with a value generator. For example:
```C#
public class ConstantValueGenerator : ValueGenerator
{
public override string Next(EntityEntry _) => "some_out_of_domain_data";
public override bool GeneratesTemporaryValues => false;
}
```C#
modelBuilder
.Entity<Blog>()
.Property<string>("some_out_of_domain_column")
.HasValueGenerator<ConstantValueGenerator>();
This will set the value for the shadow property on every new entity before it is inserted.
@ajcvickers Thanks, this is a good idea to group the default values in one place.
One more similar issue we want to report too is about HasDefaultValueSql or HasComputedColumnSql
C#
m.Property("_email")
.HasColumnName("email");
m.Property<string>("another_email_column")
.HasDefaultValueSql("[email]");
m.Property<string>("is_gmail")
.HasComputedColumnSql("IIF([email] LIKE '%@gmail.com', 1, 0)");
The another_email_column and is_gmail will still be NULL when we add entities to the DB.
I assume it is the same as HasDefaultValue where our understanding was incorrect.
Any suggestion on how to map shadow property to be the same value as another column or do some logic?
Or have some default behavior using the entity?
@jasonycw Overriding SaveChanges is probably your best bet for that at the current time.
Most helpful comment
@jasonycw It was pointed out that this can actually be done today with a value generator. For example:
```C#
public class ConstantValueGenerator : ValueGenerator
{
public override string Next(EntityEntry _) => "some_out_of_domain_data";
}
This will set the value for the shadow property on every new entity before it is inserted.