クライアントには、decimal(13,4)仕様のSQL Serverの10進数を格納する標準があります。その結果、非常に大きくてまだ成長しているスキーマでは、次のような100近くのステートメントがあります。
builder.Entity<MyObject>()
.Property(x => x.MyField1)
.ForSqlServerHasColumnType("decimal(13,4)");
builder.Entity<MyObject>()
.Property(x => x.MyField2)
.ForSqlServerHasColumnType("decimal(13,4)");
builder.Entity<MyObject2>()
.Property(x => x.MyField1)
.ForSqlServerHasColumnType("decimal(13,4)");
デフォルトですべての小数がdecimal(13,4)であることをEFに直接伝えることができる機能がある場合、それを使用したいと思います。そうでない場合は、リフレクションを使用してモデル内のすべてのオブジェクト/プロパティをループできるので、これをいくつかのステートメントで実行できますか?
何かのようなもの:
foreach(var efObj in EntityFrameWorkObjects)
{
foreach (var objProperty in efObj)
{
if (objProperty is decimal || objProperty is decimal?)
{
builder.Entity<efObj>()
.Property(x => x.efObj)
.ForSqlServerHasColumnType("decimal(13,4)");
}
}
}
オブジェクトに名前と説明がある場合、名前は必須で256文字に制限される他のいくつかの規則を実装できるため、リフレクションは素晴らしい方法のように思えます。
pdate: Ivanのコメントにあるリンクをたどり、これに合わせました。
foreach (var p in builder.Model
.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p =>
p.ClrType == typeof(decimal) ||
p.ClrType == typeof(decimal?)))
{
p.SqlServer().ColumnType = "decimal(13,4)";
}
その後まもなく、彼は完全な回答を提供しましたが、10進数とnull許容可能な10進数の両方で機能するように少し変更しました。
foreach (var pb in builder.Model
.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p =>
p.ClrType == typeof(decimal) ||
p.ClrType == typeof(decimal?))
.Select(p =>
builder.Entity(p.DeclaringEntityType.ClrType)
.Property(p.Name)))
{
pb.ForSqlServerHasColumnType("decimal(13,4)");
}
どちらの方法でも機能します。
pdate 2:上記を機能させるには、コンテキスト内でオブジェクトをDbSet <>として宣言する必要がありました。プロパティを1行ずつ設定する場合、これは必要ないようです。
EF Core v1.1.0では、次のようなものを使用できます。
foreach (var pb in modelBuilder.Model
.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?))
.Select(p => modelBuilder.Entity(p.DeclaringEntityType.ClrType).Property(p.Name)))
{
pb.ForSqlServerHasColumnType("decimal(13,4)");
}
pdate: EF Core 2.0以降、モデルはデータベースプロバイダーごとに個別に構築されるため、HasAbcXyz
メソッドは共通のHasXyz
に置き換えられます。更新されたコード(明示的に構成されたプロパティもスキップします)は次のようになります。
foreach (var property in modelBuilder.Model.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
{
if (property.Relational().ColumnType == null)
property.Relational().ColumnType = "decimal(13,4)";
}