2012-03-05 24 views
3

我需要做一些修剪,然後保存我們的數據庫中的各個領域。我們將其他應用程序的xml反序列化爲EF實體,然後插入它們。在xml中有幾個字段超過4000個字符,而不是使用TEXT數據類型,我們希望修改它們。如何在運行時檢查EF模型元數據?

我的想法是檢查MetadataWorkspaceDbChangeTrackerMyDbContext.SaveChanges()找到任何nvarchar(4000)實體屬性和修剪是比4000不再有任何字符串值,但我不知道如何處理這個。我找不到任何相關的文件。我看到一個few related questions,但沒有詳細說明或提供任何代碼示例。

這裏是我到目前爲止有:

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(); 
} 

解決方案

這裏的基礎上@ GertArnold的回答我的解決方案。

// 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); 
     } 
    } 
} 

回答

5

您可以通過這段代碼找到屬性:

var varchars = context.MetadataWorkspace.GetItemCollection(DataSpace.CSpace) 
    .Where(gi => gi.BuiltInTypeKind == BuiltInTypeKind.EntityType) 
    .Cast<EntityType>() 
    .SelectMany(entityType => entityType.Properties 
     .Where(edmProperty => edmProperty.TypeUsage.EdmType.Name == "String") 
     .Where(edmProperty => (int)(edmProperty.TypeUsage.Facets["MaxLength"] 
      .Value) >= 4000)) 
    .ToList(); 

訣竅是由BuiltInTypeKind.EntityType從模型中提取的實體類型和投這些以EntityType獲得訪問Properties。一個EdmProperty有一個屬性​​,它顯示了它們屬於哪個實體。

+0

這是醜陋的,但它的作品。謝謝! – jrummell 2012-03-06 15:23:53

+0

同意,它看起來非常容易在元數據模型中發生變化。 – 2012-03-06 15:26:19