Search code examples
entity-framework-coreef-model-builder

What is the difference between the `Has...` and `ForSqlServerHas...` extension methods in EF7 property builder?


Entity Framework 7 (Entity Framework Core) has two different sets of extension methods on PropertyBuilder. The first seems to be the "generic" set:

  • HasDefaultValueSql
  • HasColumnName
  • HasColumnType
  • HasComputedColumnSql
  • HasDefaultValue

Then there is a matching set for "ForSqlServer":

  • ForSqlServerHasDefaultValueSql
  • ForSqlServerHasColumnName
  • ForSqlServerHasColumnType
  • ForSqlServerHasComputedColumnSql
  • ForSqlServerHasDefaultValue

There also seems to be one additional "ForSqlServer" extension method with no "generic" counterpart:

  • ForSqlServerUseSequenceHiLo

What is the difference between the two groups and when do I use which one?


Solution

  • I think I've figured this out. In EF Core you are able to use different providers (at this moment SQL Server and SQLite, I believe Azure Tables are coming in the future). Since functionality for these providers are slightly different you are able to specify different behavior for the same property depending on the provider being used. In the true spirit of dependency injection, this allows you to set up one context which does not care which provider is used - leaving the choice of provider to the DI container.

    For example, I have an app which uses SQL Server in production but spins up SQLite in-memory databases for integration tests. Since SQL is slightly different between the two, I can create a property with a default value which works similarly in both:

    b.Property(x => x.ValidFrom)
        .IsRequired()
        .HasColumnName("ValidFromDate")
        .ForSqlServerHasDefaultValueSql("getutcdate()")
        .ForSqliteHasDefaultValueSql("CURRENT_TIMESTAMP");
    

    What is the difference between the two groups and when do I use which one?

    • Use the "generic" group when behavior/syntax is constant no matter the provider. In the above example, I am using the column name "ValidFromDate" for all providers.
    • Use the provider-specific method(s) when behavior/syntax depends on the provider. In the above example, behavior is the same but the actual SQL expression is different for each provider.