【问题标题】:Why does Entity Framework FindFirstOrDefault returns ExecutionException instead of null为什么实体框架 FindFirstOrDefault 返回 ExecutionException 而不是 null
【发布时间】:2020-12-29 22:20:56
【问题描述】:

我有两个表,我执行简单的db.Where(...).FirstOrDefault() 函数

OWNERS user = db.OWNERS.Where(o => o.username == owner.username).FirstOrDefault(); // works fine
SHOPS m_shop = db.SHOPS.Where(q_shop => q_shop.Name == shop.Name).FirstOrDefault(); // throws exception

第一个执行查询,如果数据不存在则返回null,问题出在第二个表。 它抛出了一个CommandExecutionException,所以我只测试了执行

SHOPS m_shop = db.SHOPS.Where(q_shop => q_shop.Name == shop.Name);

这也有效,两个表之间的唯一区别是名称列是文本,但 OWNER.username 列是 nvarchar(MAX),我尝试更新实体框架模型,但仍然遇到相同的异常。

这是表定义

CREATE TABLE [dbo].[SHOPS] (
    [Id]             DECIMAL (18)   IDENTITY (1, 1) NOT NULL,
    [Name]           TEXT           NULL,
    [location]       TEXT           NULL,
    [location_coord] NVARCHAR (MAX) NULL,
    [phone]          NVARCHAR (MAX) NULL,
    [workers_table]  DECIMAL (18)   NULL,
    CONSTRAINT [PK_SHOPS] PRIMARY KEY CLUSTERED ([Id] ASC)
);

还有我的模特:

    public partial class SHOPS
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public SHOPS()
        {
            this.OWNERSHOP = new HashSet<OWNERSHOP>();
        }

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public decimal Id { get; set; }
        public string Name { get; set; }
        public string location { get; set; }
        public string location_coord { get; set; }
        public string phone { get; set; }
        public Nullable<decimal> workers_table { get; set; }
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<OWNERSHOP> OWNERSHOP { get; set; }
    }
}

例外:

“System.InvalidCastException: 'System.Data.Entity.Infrastructure.DbQuery`1[Proje2.Models.Entity.SHOPS]' türündeki nesne 'Proje2.Models.Entity.SHOPS' türüne atılamadı.\r\n konum: Proje2.Controllers.HomeController.validateUser(SHOPS shop, OWNERS owner) C:\Users\Kutay\Documents\Visual Studio 2015\Projects\Proje2\Proje2\Controllers\HomeController.cs içinde: satır 134"

它说 `1[Proje2.Models.Entity.SHOPS]' 类型的对象无法分配给 Proje2.Models.Entity.SHOPS 类型

为什么会出现异常?提前致谢。

【问题讨论】:

  • 捕获异常并使用exception.ToString() 记录。然后在您的问题中发布该异常堆栈跟踪。
  • 我看到TEXT 类型存在很多问题,因为它根本不是文本,而是二进制类型,就像VARBINARY。顺便说一句,TEXT 是不可取的,您应该使用VARCHAR(MAX)NVARCHAR(MAX)。您是否尝试过使用转换? SHOPS m_shop = db.SHOPS.Where(q_shop =&gt; Convert.ToString(q_shop.Name) == shop.Name).FirstOrDefault()
  • @h3x0r 删除 textvarchar(max)。这些类型适用于 2GB 大小的文本,使用特殊存储。它们用于一般用途,肯定会损害性能。我怀疑你会遇到这么长的电话号码。请改用合理的长度。
  • @h3x0r VARCHAR 最大可以是 8000 或 MAX。 NVARCHAR 最大可以是 4000MAX。 MAX意味着很多。在这两种情况下,8000 和 4000 都不是任意数字,而是可以搜索的最大长度。不过,关于 4000 和 8000 阈值还有很多话要说。
  • 现在是 2020 年。TEXT 一直是 deprecated for over a decade

标签: c# entity-framework linq model-view-controller


【解决方案1】:

解决方案是为其创建自定义查询,因为显然 Entity Framework 无法自动比较文本列

将其转换为此代码行解决了我的问题。

SHOPS m_shop = db.SHOPS.SqlQuery("SELECT * FROM SHOPS WHERE Name LIKE '@Name'", new SqlParameter { SqlDbType = SqlDbType.Text, ParameterName = "@Name", Value = shop.Name }).FirstOrDefault(); 

【讨论】:

    猜你喜欢
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多