【问题标题】:Linq Error Input string was not in a correct format. System.Exception {System.FormatException}Linq 错误输入字符串的格式不正确。 System.Exception {System.FormatException}
【发布时间】:2019-01-25 22:30:54
【问题描述】:

当我尝试按字段名称uuid 查找记录时,出现以下错误:

{输入字符串的格式不正确。}

更多说明: 在 c# 中似乎从 MySQL 解析 ENUM 很麻烦

当我更改时它没有错误

public BankAccountReconciled? Reconciled { get; set; }

到:

public string Reconciled { get; set; }

现在,我需要知道如何指示 Linq 将 Enum 从 Mysql 解析回 C# Enum:

    public enum BankAccountReconciled
    {
        [Display(Name = "true")]
        True,
        [Display(Name = "false")]
        False
    }

Try/Catch 错误:

{"Input string was not in a correct format."}
-       e   {"Input string was not in a correct format."}   System.Exception {System.FormatException}

当按下 SHIFT+f9 并评估我得到以下错误:

"Method System.Data.Entity.Core.Objects.ObjectQuery`1[T] MergeAs(System.Data.Entity.Core.Objects.MergeOption) contains generic parameters"
public XeroBankAccount FindAccountByUuid(String uuid)
        {
            try
            {
                using (SyncBankDbContext dbContext = new SyncBankDbContext())
                {
                    string tempUuid = uuid;
                    var result = dbContext.XeroBankAccounts.SingleOrDefault(x => x.AccountUuid == tempUuid);
                    return result;
                }
            }
            catch (Exception e)
            {
                string errorMessage = e.Message;
                return null;
            }
        }

堆栈跟踪:

   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.String.System.IConvertible.ToInt32(IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at MySql.Data.Entity.EFMySqlDataReader.ChangeType(Object sourceValue, Type targetType)
   at MySql.Data.Entity.EFMySqlDataReader.GetValue(Int32 ordinal)
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.ErrorHandlingValueReader`1.GetUntypedValueDefault(DbDataReader reader, Int32 ordinal)
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.ErrorHandlingValueReader`1.GetValue(DbDataReader reader, Int32 ordinal)
   at lambda_method(Closure , Shaper )
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.HandleEntityAppendOnly[TEntity](Func`2 constructEntityDelegate, EntityKey entityKey, EntitySet entitySet)
   at lambda_method(Closure , Shaper )
   at System.Data.Entity.Core.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper)
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.MoveNext()
   at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
   at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__2[TResult](IEnumerable`1 sequence)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
   at SyncBank.Service.XeroAccountService.FindAccountByUuid(String uuid)

XeroBankAccount.cs:

using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using SyncBank.Xero;

namespace SyncBank.Models
{
    [Serializable]
    [Table("xero_bank_account")]
    public class XeroBankAccount
    {

        [Key]
        [Column("id")]
        public int Id { get; set; }

        [ForeignKey("XeroOrganisation")]
        [Column("organisation_id")]
        public int XeroOrganisationId { get; set; }

        public XeroOrganisation XeroOrganisation { get; set; }

        [Column("bank_id")]
        public int? BankId { get; set; }


        [Column("title")]
        [MinLength(1), MaxLength(128)]
        [Required]
        public String AccountTitle { get; set; }

        [Column("number")]
        [StringLength(50)]
        public String AccountNumber { get; set; }

        [Column("balance_statement")]
        public double? BalanceStatement { get; set; }

        [Column("balance_xero")]
        public double? BalanceXero { get; set; }

        [Column("last_statement_date")]
        public DateTime? LastStatementDate { get; set; }

        [Column("reconciled")]
        public BankAccountReconciled? Reconciled { get; set; }

        [Required]
        [Column("uuid")]
        [StringLength(256)]
        public string AccountUuid { get; set; }

        [Column("orders")]
        public int Orders { get; set; }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }

        public override bool Equals(Object obj)
        {
            // TODO: Warning - this method won't work in the case the id fields are not set
            if (!(obj is XeroBankAccount))
            {
                return false;
            }
            XeroBankAccount other = (XeroBankAccount)obj;
            return Id == other.Id;
        }

        public override String ToString()
        {
            return "org.syncbank.entity.XeroBankAccount[ accountId=" + Id + " ]";
        }
    }
}

SQL xero_bank_account:

CREATE TABLE `xero_bank_account` (
  `id` int(11) NOT NULL,
  `organisation_id` int(11) NOT NULL,
  `bank_id` int(11) DEFAULT NULL,
  `title` varchar(128) NOT NULL,
  `number` varchar(50) DEFAULT NULL,
  `balance_statement` decimal(12,2) DEFAULT NULL,
  `balance_xero` decimal(12,2) DEFAULT NULL,
  `reconciled` enum('true','false') NOT NULL DEFAULT 'false',
  `last_statement_date` datetime DEFAULT NULL,
  `uuid` varchar(256) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `orders` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `xero_bank_account`
--
ALTER TABLE `xero_bank_account`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `account_uuid` (`uuid`),
  ADD KEY `account_title_caption` (`number`),
  ADD KEY `bank_id` (`bank_id`);

【问题讨论】:

  • 数据库中的变量 ID 是字符串还是数字?你期待一个字符串。我认为数据库是一个数字。字符串 tempUuid = uuid;
  • 能否请您在FindAccountByUuid(String uuid) 中显示您在uuid 中传递的内容以及此uuid 如何存储在数据库列中?
  • 另外,添加一些记录后,您是否更改了任何列的数据类型?因此,您可能会遇到这种类型的异常。
  • 更多注意:似乎从 MySQL 解析 ENUM 在 c# 中很麻烦,当我更改时它可以正常工作
  • 尝试从public BankAccountReconciled Reconciled { get; set; } 等属性声明中删除? 并告诉我

标签: c# entity-framework linq


【解决方案1】:

例外是因为您将mysql枚举值保存为字符串truefalse,而c#中的枚举没有解析这个值,因此出现错误。

所以如果有可能,然后像这样更改 MySQL 中的枚举

`reconciled` enum(1,0) NOT NULL DEFAULT 0

然后将你的 c# 枚举成员值设置为0,1 之类的

public enum BankAccountReconciled
{
    [Display(Name = "true")]
    True = 1,                    //<= Set 1 for true that equivalent to mysql enum value 1
    [Display(Name = "false")]
    False = 0                    //<= Set 0 for false that equivalent to mysql enum value 0
}

编辑:

一种方法是让你的 mysql 枚举保持原样

`reconciled` enum('true','false') NOT NULL DEFAULT 'false',

并将您的类属性数据类型保持为string

public string Reconciled { get; set; }

并保持你的 c# 枚举相对于 mysql 枚举

public enum BankAccountReconciled
{
    [Display(Name = "true")]
    True,                      
    [Display(Name = "false")]
    False                       
}

现在只需向您的类对象添加一个属性,该属性可以将您的 string 转换为 enum 就像

public BankAccountReconciled EnumReconciled
{
    get
    {
        return GetEnumValue<BankAccountReconciled>(Reconciled);
    }
}

以上属性需要一个辅助函数,可以将你的字符串转换为枚举

public static T GetEnumValue<T>(string str) where T : struct, IConvertible
{
    Type enumType = typeof(T);
    if (!enumType.IsEnum)
    {
        throw new Exception("T must be an Enumeration type.");
    }
    T val;
    return Enum.TryParse<T>(str, true, out val) ? val : default(T);
}

输出:(来自调试器)

【讨论】:

  • 我们如何将“真”反转为“真”而不是将数值存储在数据库中?在其他情况下,我可能有“ACTIVE”、“SUSPENDED”、“DISABLED”,我希望能够在不查找文件或引用的情况下查看 DB 值
  • 如果它为 1,那么你的 c# 枚举会自动为你获取 True 枚举值
  • 是的,但我想避免使用实际值的数字表示,对于 true/false,它是有意义的,但对于 "ACTIVE"、"SUSPENDED" 、 "DISABLED" 没有意义
  • 在这种情况下,您可以像 => ACTIVE = 0SUSPENDED = 1DISABLED = 2 一样声明您的 c# 枚举,而您的 mysql 枚举将为 enum(0,1,2)...
  • 我知道你想要这样 => ACTIVE = "active", SUSPENDED = "suspended" 和你的我的 sql 枚举像 enum(active, suspended) 但不幸的是 c# 枚举值成员与字符串不兼容意味着你不能分配 ACTIVE = "active"但你可以Active = 0Active = 1000
【解决方案2】:

orders 列在数据库中标记为 null,但在 .NET 中不是可空类型(属性 Orders)。

【讨论】:

  • 不,这不是问题,在 c# 中从 MySQL 解析 ENUM 似乎很麻烦
  • 好的,很高兴你解决了!
  • 不,它没有排序,我还需要弄清楚如何反转它
猜你喜欢
  • 1970-01-01
  • 2023-03-14
  • 2011-11-23
  • 2022-06-24
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多