は私が@elbwebからコードを取り、自分の目的のためにそれを適応し、私のワンラインのソリューション
(それが1行で呼び出し、実装はもう少しです)
です。私の場合は、EDIファイルを解析していましたが、その中には15階層の階層があり、15種類すべてを明示的に指定したくなかったため、すべてのエンティティタイプで機能する1つのライナーが必要でした。
これは少し異なりますが、今は電話するのが無難です。確かにこれにパフォーマンスヒットがありますが、私にとっては受け入れられます。基本的にDbContextクラスの内部に配置し、手動で呼び出すための1ライナーです(または、SaveChangesをオーバーライドして呼び出すことができます)。
あなたDbContextでのコード:このコードの前
public class MyContext : DbContext
{
...
public void TruncateAllStringsOnAllEntitiesToDbSize()
{
var objectContext = ((IObjectContextAdapter) this).ObjectContext;
var stringMaxLengthsFromEdmx =
objectContext.MetadataWorkspace
.GetItems(DataSpace.CSpace)
.Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
.SelectMany(meta => ((EntityType) meta).Properties
.Where(p => p.TypeUsage.EdmType.Name == "String"))
.Select(d => new
{
MaxLength = d.TypeUsage.Facets["MaxLength"].Value,
PropName = d.Name,
EntityName = d.DeclaringType.Name
})
.Where(d => d.MaxLength is int)
.Select(d => new {d.PropName, d.EntityName, MaxLength = Convert.ToInt32(d.MaxLength)})
.ToList();
var pendingEntities = ChangeTracker.Entries().Where(e => e.State == EntityState.Added || e.State == EntityState.Modified).Select(x => x.Entity).ToList();
foreach (var entityObject in pendingEntities)
{
var relevantFields = stringMaxLengthsFromEdmx.Where(d => d.EntityName == entityObject.GetType().Name).ToList();
foreach (var maxLengthString in relevantFields)
{
var prop = entityObject.GetType().GetProperty(maxLengthString.PropName);
if (prop == null) continue;
var currentValue = prop.GetValue(entityObject);
var propAsString = currentValue as string;
if (propAsString != null && propAsString.Length > maxLengthString.MaxLength)
{
prop.SetValue(entityObject, propAsString.Substring(0, maxLengthString.MaxLength));
}
}
}
}
}
消費
try
{
innerContext.TruncateAllStringsOnAllEntitiesToDbSize();
innerContext.SaveChanges();
}
catch (DbEntityValidationException e)
{
foreach (var err in e.EntityValidationErrors)
{
log.Write($"Entity Validation Errors: {string.Join("\r\n", err.ValidationErrors.Select(v => v.PropertyName + "-" + v.ErrorMessage).ToArray())}");
}
throw;
}
、SaveChanges
はあなたがあまりにも大きかった文字列を挿入しようとしたときに上記の私の例では、キャッチをトリガーします。 TruncateAllStringsOnAllEntitiesToDbSize
行を追加した後、すぐにうまくいきます!私はこれに入ることができるいくつかの最適化があると確信していますので、批評/貢献してください! :-)
注:私はそれが一部のカラムだけのために、不思議なことに動作しますが、EF 6.1.3
でこれを試してみました。 私のケースでは、EFが任意の列から列の長さを取得できないようです。 –
@ReuelRibeiroもしあなたが再現ステップを作成して新しい質問に入れることができたら、私はそれをあなたのために修正できるかどうかを見て喜んで見ていきます。私はこのコードに問題はありませんでしたが、Entity Framework Extensionsにはこの機能が組み込まれています。 – Jaxidian