2014-09-24 16 views
7

sto usando EntityFramework 6 nel mio modello-primo progetto C# che utilizzando un database MySQL . Tutto andava bene e potevo generare il mio database senza problemi.Entity Framework MySQL tinyint (1) System.Boolean.Parse FormatException

Quindi ho modificato il file .edmx utilizzando il designer e qui ho iniziato i problemi che ho.

  • Prima il progettista non aggiorna il contenuti CSDL e il contenuto di mappatura C-S sezioni del file .edmx più. Così ho aggiornato il contenuto da solo e ho potuto finalmente compilare il progetto.

Ecco il file .edmx come è adesso e che cosa assomiglia nella finestra di progettazione:

EDMX File: http://pastebin.com/Xer9UyNR

Ed ecco il link per la vista progettista: http://i.stack.imgur.com/Vcv9W.png

  • secondo (e più importante), ottengo un FormatException quando EF cerca di ottenere un tinyint proveniente dal mio database e cambia il suo tipo in un booleano.
 
    à ArmoireOutils.App.OnNavigateMessageHandler(OnNavigateMessage message) dans c:\Users\JB\Desktop\CodingFrance\ArmoireOutils\ArmoireOutils\App.xaml.cs:line 101System.FormatException: String was not recognized as a valid Boolean.. 
    à System.Boolean.Parse(String value) 
    à System.String.System.IConvertible.ToBoolean(IFormatProvider provider) 
    à System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) 
    à MySql.Data.Entity.EFMySqlDataReader.ChangeType(Object sourceValue, Type targetType) 
    à MySql.Data.Entity.EFMySqlDataReader.GetValue(Int32 ordinal) 
    à System.Data.Entity.Core.Common.Internal.Materialization.Shaper.ErrorHandlingValueReader`1.GetUntypedValueDefault(DbDataReader reader, Int32 ordinal) 
    à System.Data.Entity.Core.Common.Internal.Materialization.Shaper.ErrorHandlingValueReader`1.GetValue(DbDataReader reader, Int32 ordinal) 
    à System.Data.Entity.Core.Common.Internal.Materialization.Shaper.GetPropertyValueWithErrorHandling[TProperty](Int32 ordinal, String propertyName, String typeName) 
    à lambda_method(Closure , Shaper) 
    à System.Data.Entity.Core.Common.Internal.Materialization.Shaper.HandleEntityAppendOnly[TEntity](Func`2 constructEntityDelegate, EntityKey entityKey, EntitySet entitySet) 
    à lambda_method(Closure , Shaper) 
    à System.Data.Entity.Core.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper) 
    à System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.RowNestedResultEnumerator.MaterializeRow() 
    à System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.RowNestedResultEnumerator.MoveNext() 
    à System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.TryReadToNextElement() 
    à System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.ReadElement() 
    à System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.MoveNext() 
    à System.Data.Entity.Internal.LazyEnumerator`1.MoveNext() 
    à System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source) 
    à System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__2[TResult](IEnumerable`1 sequence) 
    à System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot) 
    à System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[TResult](Expression expression) 
    à System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression) 
    à System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source) 
    à ArmoireOutils.Services.DataService.GetCupboardByGuid(String guid) dans c:\Users\JB\Desktop\CodingFrance\ArmoireOutils\ArmoireOutils\Services\DataService.cs:line 202 

Ecco il mio GetCupboardByGUID metodo:

public Cupboard GetCupboardByGuid(String guid) 
    { 
     using (var context = new ArmoireOutilsEntities()) 
     { 
      var cupboard = (from a in context.Cupboards 
       where a.GUID.Equals(guid) 
       select a) 
       .Include("ResidentTools") 
       .Include("Tools") 
       .Include("Users") //If I remove this, .SingleOrDefault() works fine. 
       .SingleOrDefault(); //Throw FormatException when getting the User.Active value from the database. 

      if (cupboard != null) 
       cupboard.RefreshLists(); 

      return cupboard; 
     } 
    } 

E qui è la mia classe utente generato dal TT edmx:

public partial class User 
{ 
    public User() 
    { 
     this.Tools = new ObservableCollection<Tool>(); 
     this.Cupboards = new ObservableCollection<Cupboard>(); 
     this.Active = true; 
    } 

    public int Id { get; set; } 
    public short Type { get; set; } 
    public string Firstname { get; set; } 
    public string LastName { get; set; } 
    public string Login { get; set; } 
    public short Gender { get; set; } 
    public short LangId { get; set; } 
    public string Photo { get; set; } 
    public System.DateTime CreationDate { get; set; } 
    public Nullable<System.DateTime> ModificationDate { get; set; } 
    public Nullable<System.DateTime> LastConnection { get; set; } 
    public Nullable<System.DateTime> DisableDate { get; set; } 
    public bool Active { get; set; } 

    public virtual Lang Lang { get; set; } 
    public virtual IList<Tool> Tools { get; set; } 
    public virtual IList<Cupboard> Cupboards { get; set; } 
} 

Quindi credo che EF è iterazione su tutti gli utenti del DB che si trovano nell'armadio (t egli tavolo collegando un utente ad un armadio per la relazione molti-a-molti) e quando si tratta di impostare l'Active valore di per il primo utente, si ottiene 1 dal DB ottenerlo come String per prima cosa, quindi prova ad analizzare quella stringa in un booleano usando System.Boolean.Parse ma il metodo thaat non supporta numeri come "1" per vero (il campo nel DB è un tinyint (1)).

Quindi, perché EF non è in grado di capire che era un minuscolo quindi non può usarlo in System.Boolean.Parse?

ho cercato di rigenerare l'intero file .edmx dal database => stessa eccezione

ho cercato di rigenerare l'intero .edmx di file da zero => stessa eccezione

Non capisco perché, perché non ho modificato il modello di utente in modo che il campo attivo era già lì e stava lavorando bene.

Scusate per il post lungo e grazie in anticipo.

Con i migliori saluti, theCivilian

+0

Devi dire a MySql di trattare tinyint come booleano, nella stringa di connessione. –

+0

@GertArnold, Grazie per il suggerimento, ma sfortunatamente dice ** "La parola chiave 'trattamento piccolo come booleano' non è supportata." ** Anche questo valore è ** true ** per impostazione predefinita in base alla documentazione. (Sto usando ** MySQL-Connector 6.8.3 ** – tehCivilian

risposta

10

Configurare il tipo di dati su un soggetto specifico:

modelBuilder.Entity<User>() 
        .Property(p => p.Active) 
        .HasColumnType("bit"); 

o generale:

modelBuilder.Properties() 
      .Where(x => x.PropertyType == typeof(bool)) 
      .Configure(x => x.HasColumnType("bit")); 
+0

Confermato di lavorare per me! – Jogai

+0

C'è un modo per farlo se stiamo facendo DB prima? Non so dove applicare la modifica. – sobelito

0

Se si sta facendo questo DB prima, è sufficiente modificare il TINYINT (1) digita BIT (1), assumendo che tu voglia veramente un booleano. Potrebbe essere necessario aggiornare anche i valori predefiniti (alla sintassi dei bit come b'0 '). EF tradurrà ancora questi valori in valori booleani nelle tue entità.

Problemi correlati