EF6 Migrations Precision in MetadataType

141 views Asked by At

I'm trying to set Precision through MetadataType in EF6 Code First Migrations. If I set the attribute directly on the property in the class, it works correctly, but not if it's in the MetadataType class.

Is there anything I can do to get this to work (besides decorating them directly in the class)?

The Precision solution is originally in C#.

I'd be happy to accept an answer in C#...I'll convert it.

Use case: The original class is not in my code / control.

Test Console App

Imports System.IO
Imports System.Data.Entity
Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel.DataAnnotations.Schema

Module Module1

    Friend MyAppSettings As New AppSettings
    Friend SqlConnect As String = String.Empty

    Sub Main()
        With New SqlClient.SqlConnectionStringBuilder() With {
            .DataSource = Path.Combine(MyAppSettings.SqlServer, MyAppSettings.SqlInstance),
            .InitialCatalog = MyAppSettings.SqlDatabase,
            .IntegratedSecurity = True, .PersistSecurityInfo = True,
            .MultipleActiveResultSets = True}

            SqlConnect = .ConnectionString
        End With

        With New MyEntities(SqlConnect)
            Try
                .Database.Initialize(True)
            Catch ex As Exception
                Debug.Print(ex.ToString)
            Finally
                .Dispose()
            End Try
        End With
    End Sub

End Module

<MetadataType(GetType(TestMetaData))>
Partial Public Class Test
    <Key>
    Public Property ID As Int64 = 0

    Public Property Description As String = String.Empty

    ' ** Precision works with Migrations when applied directly here **
    '<Precision(12, 6)>
    Public Property Measurement As Decimal?
End Class

Public Class TestMetaData
    <Column(TypeName:="varchar"), StringLength(100)>
    Public Property Description As String = String.Empty

    ' ** Precision FAILS with Migrations when applied through MetadataType **
    <Precision(15, 6)>
    Public Property Measurement As Decimal?
End Class

Public Class MyEntities
    Inherits DbContext

    Public Sub New()
        Database.SetInitializer(New MigrateDatabaseToLatestVersion(Of MyEntities, Migrations.Configuration)(True))
    End Sub

    Public Sub New(ConnectionString As String)
        MyBase.New(ConnectionString)
        Database.SetInitializer(New MigrateDatabaseToLatestVersion(Of MyEntities, Migrations.Configuration)(True))
    End Sub

    Protected Overrides Sub OnModelCreating(ModelBuilder As DbModelBuilder)
        Precision.ConfigureModelBuilder(ModelBuilder)
    End Sub

    Public Overridable Property TestData() As DbSet(Of Test)
End Class

<AttributeUsage(AttributeTargets.Property, AllowMultiple:=False)>
Public Class Precision
    Inherits Attribute

    Public Property Precision() As Byte
    Public Property Scale() As Byte

    Public Sub New(Precision As Byte, Scale As Byte)
        Me.Precision = Precision
        Me.Scale = Scale
    End Sub

    Public Shared Sub ConfigureModelBuilder(ByRef ModelBuilder As DbModelBuilder)
        With ModelBuilder.Properties.Where(Function(x) x.GetCustomAttributes(False).OfType(Of Precision).Any)
            .Configure(Function(c) c.HasPrecision(c.ClrPropertyInfo.GetCustomAttributes(False).OfType(Of Precision).First.Precision,
                                                  c.ClrPropertyInfo.GetCustomAttributes(False).OfType(Of Precision).First.Scale))
        End With
    End Sub

End Class

Migrations Code

Imports System.Data.Entity.Migrations

Namespace Migrations

    Friend NotInheritable Class Configuration
        Inherits DbMigrationsConfiguration(Of MyEntities)

        Public Sub New()
            AutomaticMigrationsEnabled = False
            AutomaticMigrationDataLossAllowed = True
        End Sub
    End Class

    Partial Public Class BaseSchema
        Inherits DbMigration

        Public Overrides Sub Up()
            CreateTable(
                "dbo.Tests",
                Function(c) New With
                    {
                        .Clever_EDI_ID = c.Long(nullable:=False, identity:=True),
                        .Description = c.String(maxLength:=100, unicode:=False),
                        .Measurement = c.Decimal(precision:=18, scale:=2)
                    }) _
                .PrimaryKey(Function(t) t.Clever_EDI_ID)
        End Sub

        Public Overrides Sub Down()
            DropTable("dbo.Tests")
        End Sub
    End Class

End Namespace
0

There are 0 answers