2009-07-13 33 views
7

我正在使用ADO.NET Entity-Framework ObjectContext來訪問我的數據存儲。有沒有讓實體框架將空字符串還原爲空的選項?

我想如果值設置爲空字符串,它們應該自動變爲空。

+1

從另外一個論壇上,我得到這個答案http://msdn.microsoft.com/en-us/library/vstudio/ms366709(v=vs.100).aspx(ConvertEmptyStringToNull屬性) – Naomi 2014-09-29 15:44:31

+0

嗨納奧米,我很高興你找到了它,爲什麼不自己回答? – Shimmy 2014-09-30 23:27:07

回答

5

我居然找到一個更好的辦法這實際上是在系統中構建的,再加上它使用實體的內部序數元數據(我沒有測試性能差異,但這應該比反射快得多):

private const string StringType = "String"; 
private const EntityState SavingState = EntityState.Added | EntityState.Modified; 
public override int SaveChanges() 
{ 
    //when using on ObjectContext replace 'objectContext' with 'this', 
    //and override SaveChanges(SaveOptions options) instead: 

    var objectContext = ((IObjectContextAdapter)this).ObjectContext; 
    var savingEntries = objectContext.ObjectStateManager 
    .GetObjectStateEntries(SavingState); 

    foreach (var entry in savingEntries) 
    { 
    var curValues = entry.CurrentValues; 
    var fieldMetadata = curValues.DataRecordInfo.FieldMetadata; 
    var stringFields = fieldMetadata 
     .Where(f => f.FieldType.TypeUsage.EdmType.Name == StringType); 
    foreach (var stringField in stringFields) 
    { 
     var ordinal = stringField.Ordinal; 
     var curValue = curValues[ordinal] as string; 
     if (curValue != null && curValue.All(char.IsWhiteSpace)) 
     curValues.SetValue(ordinal, null); 
    } 
    } 
    return base.SaveChanges(); //SaveChanges(options) on ObjectContext 
} 
1

不是我所知道的。

你可能編寫從ObjectContext繼承一個類並重寫SaveChanges()做到這一點,用它來代替你的x.objectlayer.cs/x.designer.cs ObjectContext

+0

哎呀,雖然即時編寫這個你發佈它...大聲笑 謝謝,我投了 – Shimmy 2009-07-13 14:22:39

7

如果你使用Entity Framework 4,你可以使用T4模板來完成留下這個。只要將它放在.tt模板文件中每個字符串屬性的getter中,它就會用null替換空字符串並自動修剪字符串。無需使用反射。

<#+ if (primitiveProperty.TypeUsage.ToString().Split('.').Last() == "String") { #> 
    if (value == "") value = null; 
    else value = value.Trim(); 
<#+ } #> 
+0

我們使用反向POCO生成器,我實際上需要相反(將空字符串轉換爲空)。你知道你的建議是否適用於這種情況? – Naomi 2014-09-29 15:34:06

2

我剛剛調整了上面的代碼到新版本的實體框架4.1(DbContext)。

public override int SaveChanges() 
    { 
     var objContext = ((IObjectContextAdapter)this).ObjectContext; 
     var entries = objContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified).Select(
       entry => entry.Entity); 
     foreach (var entity in entries) 
     { 
      string str = typeof(string).Name; 
      var properties = from p in entity.GetType().GetProperties() 
          where p.PropertyType.Name == str 
          select p; 

      foreach (var item in properties) 
      { 
       string value = (string)item.GetValue(entity, null); 
       if (value != null && value.Trim().Length == 0) 
       { 

        item.SetValue(entity, null, null); 

       } 
      } 
     } 
     return base.SaveChanges(); 
0

而不是通過重寫的ObjectContext複雜的東西我用字符串擴展方法值轉換爲數據庫存儲

public static class StringExtensions 
{ 
    public static string EmptyStringToNull(this string s) 
    { 
     return string.IsNullOrWhiteSpace(s) ? null : s; 
    } 

    public static object EmptyStringToDBNull(this string s) 
    { 
     if (string.IsNullOrWhiteSpace(s)) 
      return DBNull.Value; 
     else 
      return s; 
    } 
} 
0

只是爲了完整性,這裏寫成的部分類,而不是繼承接受的答案。請注意,此版本還修剪字符串。

using System.Data; 
using System.Data.Objects; 
using System.Linq; 
public partial class MyObjectContext { 
    private const string StringType = "String"; 
    private const EntityState SavingState = EntityState.Added | EntityState.Modified; 

    public override int SaveChanges(SaveOptions options) { 
     var savingEntries = this.ObjectStateManager.GetObjectStateEntries(SavingState); 

     foreach (var entry in savingEntries) { 
      var curValues = entry.CurrentValues; 
      var fieldMetadata = curValues.DataRecordInfo.FieldMetadata; 
      var stringFields = fieldMetadata.Where(f => f.FieldType.TypeUsage 
                 .EdmType.Name == StringType); 

      foreach (var stringField in stringFields) { 
       var ordinal = stringField.Ordinal; 
       var curValue = curValues[ordinal] as string; 

       if (curValue != null && curValue.All(char.IsWhiteSpace)) { 
        curValues.SetValue(ordinal, null); 
       } 
       else if (curValue != null && curValue != curValue.Trim()) { 
        curValues.SetValue(ordinal, curValue.Trim()); 
       } 
      } 
     } 
     return base.SaveChanges(options); 
    } 
} 

我還展示了所需的usings,因爲我發現它令人沮喪,當我copy'n'paste代碼和IDE拋出了有關類型或命名空間不是發現了一些錯誤。

0

我用Shimmy's solution,很高興,直到我發現我的複雜類型中的字符串被遺漏。換句話說,我需要一種方法來清除不可空白的字符串,不僅在我的核心對象/記錄中,而且還包括它的任何非原始對象屬性,以及它們的屬性...

以下是我的遞歸適應。我不能說它的優雅和生產質量,因爲它沒有長時間的生活,但它似乎對我來說至今還在工作,並且至少可以作爲其他人的起點。

using System.Data.Entity; 
using System.Data.Entity.Core.Metadata.Edm; 
using System.Data.Entity.Core.Objects; 
using System.Data.Entity.Infrastructure; 
using System.Linq; 

public class MyDataContext : DbContext 
{ 
    public override int SaveChanges() 
    { 
     ObjectStateEntry[] savingObjectStateEntries = ((IObjectContextAdapter)this) 
      .ObjectContext.ObjectStateManager 
      .GetObjectStateEntries(EntityState.Added | EntityState.Modified).ToArray(); 
     foreach (ObjectStateEntry savingObjectStateEntry in savingObjectStateEntries) 
      SetEmptyStringsToNull(savingObjectStateEntry.CurrentValues); 

     return base.SaveChanges(); 
    } 

    private static void SetEmptyStringsToNull(CurrentValueRecord currentValueRecord) 
    { 
     if (currentValueRecord != null) 
      for (int i = 0; i < currentValueRecord.FieldCount; i++) 
       if (currentValueRecord[i] is CurrentValueRecord) 
        SetEmptyStringsToNull(currentValueRecord[i] as CurrentValueRecord); 
       else if ((currentValueRecord[i] is string) 
        && (currentValueRecord.DataRecordInfo.FieldMetadata[i].FieldType as EdmProperty).Nullable 
        && string.IsNullOrWhiteSpace(currentValueRecord[i] as string)) 
        currentValueRecord.SetValue(i, null); 
    } 
} 
1

這裏是一個實體框架核心(V2測試)的解決方案。由於文檔有限,不得不通過API來實現我的方式,所以可能有其他方法來完成相同的事情。請注意,使用此方法修改原始對象。

public override int SaveChanges() 
{ 
    ConvertWhitespaceToNulls(); 
    return base.SaveChanges(); 
} 


private void ConvertWhitespaceToNulls() 
{ 
    var entityEntries = this.ChangeTracker 
     .Entries() 
     .Where(x => x.State == EntityState.Modified || x.State == EntityState.Added && x.Entity != null); 

    foreach (var e in entityEntries) 
     foreach (var currentValue in e.CurrentValues.Properties.Where(p => p.ClrType == typeof(string) && p.IsNullable)) 
      if (string.IsNullOrWhiteSpace((string) currentValue.FieldInfo.GetValue(e.Entity))) 
       currentValue.FieldInfo.SetValue(e.Entity, null); 
}