私たちのデータベースにさまざまなフィールドを保存する前にトリミングする必要があります。別のアプリケーションからxmlをEFエンティティに非直列化してから挿入します。 xmlに4000文字を超えるフィールドはほとんどなく、TEXTデータ型を使用するのではなく、代わりにトリムする必要があります。実行時にEFモデルメタデータを検査する方法は?
私の考えはどのnvarchar(4000)
エンティティプロパティを見つけて、4000よりも長く、しかし、私はこれにアプローチする方法が分からない任意の文字列値をトリムするMyDbContext.SaveChanges()
内MetadataWorkspace
とDbChangeTracker
を検査することでした。私は関連文書を見つけることができませんでした。私はfew related questionsを見ましたが、細かいことはありませんでした。
は、ここで私はこれまで持っているものです。ここに私のソリューションは、@ GertArnoldの回答に基づいています
public override int SaveChanges()
{
//TODO: trim strings longer than 4000 where type is nvarchar(max)
MetadataWorkspace metadataWorkspace =
((IObjectContextAdapter) this).ObjectContext.MetadataWorkspace;
ReadOnlyCollection<EdmType> edmTypes =
metadataWorkspace.GetItems<EdmType>(DataSpace.OSpace);
return base.SaveChanges();
}
ソリューション
。
// get varchar(max) properties
var entityTypes = metadataWorkspace.GetItems<EntityType>(DataSpace.CSpace);
var properties = entityTypes.SelectMany(type => type.Properties)
.Where(property => property.TypeUsage.EdmType.Name == "String"
&& property.TypeUsage.Facets["MaxLength"].Value.ToString() == "Max"
// special case for XML columns
&& property.Name != "Xml")
.Select(
property =>
Type.GetType(property.DeclaringType.FullName)
.GetProperty(property.Name));
// trim varchar(max) properties > 4000
foreach (var entry in ChangeTracker.Entries())
{
var entity = entry.Entity;
var entryProperties =
properties.Where(prop => prop.DeclaringType == entity.GetType());
foreach (var entryProperty in entryProperties)
{
var value =
((string) entryProperty.GetValue(entity, null) ?? String.Empty);
if (value.Length > 4000)
{
entryProperty.SetValue(entity, value.Substring(0, 4000), null);
}
}
}
これは醜いですが、動作します。ありがとう! – jrummell
同意すると、メタデータモデルの変更に非常に敏感です。 –