【问题标题】:EF Core 3.1.1 Avoiding the exception "The data types text and varchar are incompatible in the equal to operator" just as LINQPad 6 doesEF Core 3.1.1 避免异常“数据类型 text 和 varchar 在等于运算符中不兼容”,就像 LINQPad 6 一样
【发布时间】:2020-05-19 07:02:23
【问题描述】:

我正在尝试通过 Entity Framework Core 3.1.1 运行此 LINQ 表达式。

 using (Text3Context text3Context = new Text3Context(_constringText3))
            {
                var aus = text3Context.Ausschreibungen.Where(a => a.InhaltKurzText.Contains(value)).Select(c => c.InhaltKurzText).ToList();
            }

不幸的是,它抛出了异常:“数据类型 text 和 varchar 在等于运算符中不兼容”但是,当我在 LINQPad 6 中运行相同的表达式时:

string value = "test";
var aus = Ausschreibungen.Where(a => a.InhaltKurzText.Contains(value)).Select(c => c.InhaltKurzText);
aus.Dump();

完美运行,没有错误。

如您所见,sql 查询略有不同:

Linq/EF 核心:

SELECT [a].[InhaltKurzText]
FROM [dbo].[Ausschreibungen] AS [a]
WHERE (@__value_0 = '''') OR (CHARINDEX(@__value_0, [a].[InhaltKurzText]) > 0)',N'@__value_0 text',@__value_0='test'

LINQPad:

SELECT [a].[InhaltKurzText]
FROM [Ausschreibungen] AS [a]
WHERE ((@__value_0 = N'''') AND @__value_0 IS NOT NULL) OR (CHARINDEX(@__value_0, [a].[InhaltKurzText]) > 0)',N'@__value_0 nvarchar(16)',@__value_0=N'test'

我怎样才能像 LINQPad 一样处理这个查询?

“InhaltKurzText”的 sql-datatype 是“text”,这就是异常的原因,但是,不幸的是,更改 sql-datatype 不是一种选择,而且解决方法是“昂贵的”我希望能够以与 LINQPad 相同的方式运行它。

依赖Microsoft.Data.Sql.Client的版本是1.0.19.269.1。

提前致谢

【问题讨论】:

  • 与LINQPad无关,而是使用的EF Core版本。看起来 ER Core 3.x 暗示的数据库类型与 LINQPad 使用的 EF Core 2.x 不同。
  • 你可以试试Like,但效率不高:.Where(a => EF.Functions.Like(a.InhaltKurzText, $"%{value}%"))
  • @IvanStoev 两者都在使用 EF Core 3.1。
  • LINQPad 将参数类型推断为 nvarchar(16)(可能由 EF 调解)似乎毫无意义。如果您使用12345678901234567 作为值会发生什么情况,它是否会提高到nvarchar(32)?如果知道基础列是 textvarchar(max) (而不是 text 仅仅因为它匹配),那么可以说是最好的参数类型,但这是另一罐 bean。
  • 您应该努力将数据类型 Text 更改为现代替代品 varchar(max)。自 SQL Server 2008 以来,Text 数据类型已被弃用,它比当前最旧的受支持版本旧一个版本。如果更改 sql 数据类型不是一个选项,你最好把它作为一个选项,否则,它会在以后咬你。

标签: c# sql linq entity-framework-core linqpad


【解决方案1】:

这似乎是由 EF Core 3.x 基础架构和/或 SqlServer 提供程序中的一些更改引起的。 LINQPad 无关紧要,因为它只是将 LINQ 查询委托给底层框架(在您的情况下显然是 EF Core 2.x)。

根据SqlServerdocumentationtext数据类型已经过时,代表

服务器代码页中的可变长度非 Unicode 数据,最大字符串长度为 2^31-1 (2,147,483,647)。

所以即使数据库类型是text,您也可以在EF Core 中将其映射为varchar(2^31-1)

modelBuilder.Entity<Ausschreibungen>().Property(e => e.InhaltKurzText)
    .IsUnicode(false)
    .HasMaxLength((1 << 31) - 1);

有趣的是,生成的 SQL 与从

生成的 SQL 完全相同(根据 EF Core 日志)
modelBuilder.Entity<Ausschreibungen>().Property(e => e.InhaltKurzText)
    .HasColumnType("text");

但运行成功,而后者生成有问题的运行时异常。

【讨论】:

  • 这应该小心使用,因为如果第一个版本推断出最大长度为2^31VARCHAR 是合适的,那么对于大于8000 的值,这将失败,即VARCHAR 不是 VARCHAR(MAX) 的 i>实际 限制(但这很可能是 EF 中长度超过 8000 的特殊情况,我没有检查过)。
  • 注意(1 &lt;&lt; 30) - 1不是2^31-1;更简洁地写成Int32.MaxValue
  • @JeroenMostert 当然你是对的,我只是想从文档中获取价值,但是在到处查看时犯了一个错误:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多