2014-09-24 3 views
7

Я использую EntityFramework 6 в моем C# модели-первых проекта, с использованием базы данных MySQL . Все было в порядке, и я мог бы сгенерировать свою базу данных без проблем.Entity Framework MySQL TINYINT (1) System.Boolean.Parse FormatException

Затем я модифицировал свой файл .edmx с помощью конструктора, и здесь возникли проблемы, которые у меня есть.

  • Сначала дизайнер не обновляет содержимое CSDL и содержание отображения C-S секций EDMX-файла больше. Итак, я сам обновил содержимое и смог, наконец, скомпилировать проект.

Вот файл EDMX-, как это прямо сейчас, и что это выглядит как в конструкторе:

EDMX Файл: http://pastebin.com/Xer9UyNR

А вот ссылка на мнение дизайнера: http://i.stack.imgur.com/Vcv9W.png

  • Второй (и самый важный), я получаю исключение FormatException, когда EF пытается получить tinyint, исходящий из моей базы данных и измените его тип на логическое.
 
    à 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 

Вот мой GetCupboardByGUID метод:

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

А вот мой класс пользователя генерируется EDMX-TT:

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

Так что я думаю EF итерация над всеми пользователями из БД, которые находятся в cupboarduser (вкладка ле связывание пользователя к шкафу для многих-ко-многим), а когда дело доходит до установки значения активного для первого пользователя, он получает 1 из БДА получить его в качестве строки первых а затем попытайтесь проанализировать эту строку в логическом режиме, используя System.Boolean.Parse, но метод thaat не поддерживает числа, подобные «1» для истины (поле в БД - это tinyint (1)).

Итак, почему EF не может понять, что это был tinyint, поэтому он не может использовать его в System.Boolean.Parse?

Я пытался регенерировать весь EDMX- файл из базы данных => То же исключение

Я пытался регенерировать весь .EDMX файл с нуля => То же исключение

Я не понимаю, почему, потому что я не изменить модель пользователя, так что поле Активный уже был там и работал просто отлично.

Извините за длинный пост и спасибо заранее.

С наилучшими пожеланиями, theCivilian

+0

Вы должны сказать MySql, чтобы рассматривать tinyint как boolean в строке соединения. –

+0

@ GertArnold, спасибо за предложение, но, к сожалению, он говорит ** «Ключевое слово« обрабатывать крошечные как логические »не поддерживается». ** Также это значение ** истинно ** по умолчанию в соответствии с документацией. (Я использую ** MySQL-Connector 6.8.3 ** – tehCivilian

ответ

10

Настройка типов данных на конкретной Сущности:

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

или вообще:

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

Подтвержденная работа для меня! – Jogai

+0

Есть ли способ сделать это, если мы делаем БД первым? Не знаете, где применить изменение. – sobelito

0

Если вы делаете это DB первым, просто измените TINYINT (1) относится к BIT (1), предполагая, что вы действительно хотите булево. Возможно, вам придется обновлять значения по умолчанию также (для синтаксиса бит, такого как b'0 '). EF все равно переводит их в логические значения в ваших сущностях.