2009-07-13 18 views
7

Sto usando un ObjectContext di Entity-Framework ADO.NET per accedere al mio archivio dati.Esiste un'opzione per fare in modo che Entity Framework ripristini le stringhe vuote su null?

Voglio che se i valori siano impostati con stringhe vuote, dovrebbero diventare automaticamente nulli.

+1

da un altro forum ho avuto questa risposta http://msdn.microsoft.com/en-us/library/vstudio/ms366709(v=vs.100).aspx (ConvertEmptyStringToNull proprietà) – Naomi

+0

Ciao Naomi, io Sono contento che tu l'abbia trovato, perché non fai una tua risposta? – Shimmy

risposta

5

in realtà ho trovato un modo migliore per questo, in realtà è incorporato nel sistema, in più utilizza i metadati ordinali interni delle entità che vengono caricati comunque (non ho testato la differenza di prestazioni, ma dovrebbe essere molto più veloce della riflessione):

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

Non che io sappia.

Si potrebbe scrivere una classe che eredita da ObjectContext e ignorare SaveChanges() per farlo e l'uso che invece di ObjectContext nei vostri x.objectlayer.cs/x.designer.cs

+0

oops, mentre sto scrivendo questo lo hai postato ...lol grazie, ho votato – Shimmy

7

Se si utilizza Entity Framework 4, è possibile utilizzare i modelli T4 per questo Basta posizionarlo nel getter di ogni proprietà di stringa nel file modello .tt, e sostituirà le stringhe vuote con le stringhe null e taglia automaticamente. Non c'è bisogno di usare la riflessione.

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

Utilizziamo il generatore POCO inverso e in realtà ho bisogno del contrario (converti stringhe null vuote). Sai se il tuo suggerimento è valido per questo scenario? – Naomi

2

Ho appena adattato il codice qui sopra per la nuova versione di Entity Framework 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

Invece di complicare le cose sovrascrivendo l'ObjectContext io uso i metodi di estensione delle stringhe per convertire i valori per l'archiviazione di database

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

Sei sicuro che funzionerà su query DB? Credo che non lo farà. – Shimmy

0

Solo per completezza, ecco la risposta accettata scritto come una classe parziale invece di ereditaria . Si noti che questa versione taglia anche le stringhe.

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

ho anche mostrato la necessaria usings perché lo trovo frustrante quando ho Copy'n'Paste codice e l'IDE solleva alcuni errori circa tipo o dello spazio dei nomi non trovato.

0

Ho usato Shimmy's solution e sono stato contento fino a quando ho scoperto che le stringhe nei miei tipi complessi erano mancate. In altre parole, avevo bisogno di un modo per azzerare le stringhe nullabili solo per lo spazio non solo del mio oggetto/record principale, ma di tutte le sue proprietà dell'oggetto non primitive, e loro e loro ...

Di seguito è riportato il mio adattamento ricorsivo. Non posso parlare con la sua eleganza o qualità di produzione perché non è vissuto per molto tempo, ma sembra che funzioni per me finora e possa almeno servire da punto di partenza per qualcun altro.

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

Ecco una soluzione per Entity Framework Core (testato in V2). Ho dovuto attraversare l'API a causa della documentazione limitata, quindi potrebbero esserci altri modi per realizzare la stessa cosa. Si noti che gli oggetti originali vengono modificati utilizzando questo metodo.

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); 
} 
Problemi correlati