Note: an answer in either VB.NET or C# will be fine. I have no preference.
I'm using table-per-type architecture.
I want all of my entities to have a second key column (of type Guid
), so I've created a base class like this:
Public MustInherit Class Entity
Public Property Id As Integer
Public Property Key As Guid
End Class
Public Class City
Inherits Entity
Public Property Name As Integer
Public Property Code As String
End Class
I want each of these columns to self-populate at the database level (SQL Server) when a new row is added, so I've created a configuration like this:
Public Class EntityConfiguration
Implements IEntityTypeConfiguration(Of Entity)
Public Sub Configure(Builder As EntityTypeBuilder(Of Entity)) Implements IEntityTypeConfiguration(Of Entity).Configure
Builder.Property(Function(Entity) Entity.Key).IsRequired.HasDefaultValueSql("NEWID()")
End Sub
End Class
This works—the column is added correctly—but the migrations generator builds code for one table only, named Entities
.
I tried this in my CityConfiguration
class:
Builder.ToTable("Cities")
...but the generator still includes an Entity
table. This is undesirable for obvious reasons. Entity
is a base class only. And the Key
column is omitted from the Cities
table.
Is there a way to have all of my entities contain this common Key
column without having to include an explicit call to HasDefaultValueSql("NEWID()")
in each entity's configuration? That's going to be tedious and error-prone.
Well, shucks... that didn't take long.
A quick-and-dirty extension method gets us there just nicely:
Public Module Extensions
<Extension>
Public Sub AddKey(Of TEntity As Entity)(Builder As EntityTypeBuilder(Of TEntity))
Builder.Property(Function(Entity) Entity.Key).IsRequired.HasDefaultValueSql("NEWID()")
Builder.HasIndex(Function(Entity) Entity.Key).IsUnique()
End Sub
End Module
And then we just call it like this in each entity's configuration:
Builder.AddKey
I'll leave this Q&A up in case anyone wants to use the idea.
--EDIT--
Possibly even cleaner would be to use a base class:
Public MustInherit Class BaseConfiguration(Of T As Entity)
Public Overridable Sub Configure(Builder As EntityTypeBuilder(Of T))
Builder.Property(Function(Entity) Entity.Key).IsRequired.HasDefaultValueSql("NEWID()")
Builder.HasIndex(Function(Entity) Entity.Key).IsUnique()
End Sub
End Class
Just make sure it doesn't implement IEntityTypeConfiguration(Of Entity)
, or an unwanted Entity
table will be generated.
Use it like this:
Public Class CityConfiguration
Inherits BaseConfiguration(Of City)
Implements IEntityTypeConfiguration(Of City)
Public Overrides Sub Configure(Builder As EntityTypeBuilder(Of City)) Implements IEntityTypeConfiguration(Of City).Configure
Builder.Property(Function(City) City.Code).IsRequired.HasDefaultValue(String.Empty).HasMaxLength(7)
Builder.Property(Function(City) City.Name).IsRequired.HasDefaultValue(String.Empty).HasMaxLength(25)
Builder.HasIndex(Function(City) City.Code).IsUnique()
Builder.HasIndex(Function(City) City.Name)
MyBase.Configure(Builder)
End Sub
End Class