c# - Entity Framework 从表达式生成错误的参数类型

标签 c# sql-server entity-framework

EF 正在创建一个接收 int 作为参数的查询。它应该是一个 varchar。

我有这个生成表达式的 C# 代码

Expression<Func<Documento, bool>> query = (t => (string)t.NumeroDocumento.ToString() == (string)numeroOriginal.ToString());

var documento = documentoRepository.Obter(query, propriedadesIncluidas: "PapelPessoa.Pessoa");

Documento.Numero documento 是一个字符串。数据库表中的相应字段是 varchar(50)。 numeroOriginal 也是一个字符串。

以及存储库中获取 (get) 的代码

private T Obter(Expression<Func<T, bool>> filtro, string propriedadesIncluidas)
    {
        IQueryable<T> query = dbSet;

        if (filtro != null)
            query = query.Where(filtro);

        if (!string.IsNullOrWhiteSpace(propriedadesIncluidas))
        {
            foreach (var includeProperty in propriedadesIncluidas.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                query = query.Include(includeProperty);
        }

        return query.FirstOrDefault();
    }

当 EF 创建 sql 查询时,它会创建此查询(从调试器获得)

SELECT     [Extent1].[id] AS [id],     [Extent1].[numero_documento] AS [numero_documento],     
-- Removed for clariry
FROM [dbo].[DOCUMENTO] AS [Extent1]    
WHERE [Extent1].[numero_documento] = (CASE WHEN (@p__linq__0 IS NULL) THEN N'' ELSE @p__linq__0 END)

替换参数后,这将转换为

SELECT     [Extent1].[id] AS [id],     [Extent1].[numero_documento] AS [numero_documento],     
-- Removed for clariry
FROM [dbo].[DOCUMENTO] AS [Extent1]    
WHERE [Extent1].[numero_documento] = 47837

正确的查询应该是

SELECT     [Extent1].[id] AS [id],     [Extent1].[numero_documento] AS [numero_documento],     
-- Removed for clariry
FROM [dbo].[DOCUMENTO] AS [Extent1]    
WHERE [Extent1].[numero_documento] = '47837'

两者都有效,但第二个比第一个快得多(我的意思是快得多)。我在 SQL 管理工作室中运行了这两个。 EF 获取的参数类型错误?我该如何解决?我需要更改代码或数据库吗?表的 EF 配置是否错误?

这是 EF 对象:

[Table("DOCUMENTO")]
    public class Documento : EntidadeBase
    {

        [Column("numero_documento", TypeName = "varchar")]
        [Display(Name = "Numero")]
      public string NumeroDocumento { get; set; }

// removed for clarity
}

这是表格

CREATE TABLE [dbo].[DOCUMENTO](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [numero_documento] [varchar](50) NULL,
-- removed for clarity
}

最佳答案

我怀疑这个实体/列周围的配置有些不同,或者可能是上下文导致了这种情况。我试图重现该问题,但我没有遇到同样的问题:

我在我的一个测试表中添加了一个 varchar 列,并为其提供了数值以供搜索。

与你所拥有的类型转换相同:

Expression<Func<Course, bool>> where = (x => (string)x.SomeNumber.ToString() == (string)testId.ToString());

我从 EF 得到一条 SQL 语句:

exec sp_executesql N'SELECT 
    [Extent1].[CourseId] AS [CourseId], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[SomeNumber] AS [SomeNumber]
    FROM [dbo].[Courses] AS [Extent1]
    WHERE ((CASE WHEN ([Extent1].[SomeNumber] IS NULL) THEN N'''' ELSE [Extent1].[SomeNumber] END) = (CASE WHEN (@p__linq__0 IS NULL) THEN N'''' ELSE @p__linq__0 END)) OR ((CASE WHEN ([Extent1].[SomeNumber] IS NULL) THEN N'''' ELSE [Extent1].[SomeNumber] END IS NULL) AND (CASE WHEN (@p__linq__0 IS NULL) THEN N'''' ELSE @p__linq__0 END IS NULL))',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'12'
go

过滤器读取为 N'12'

如果我删除不必要的转换(DB 列是 varchar(50) 并且正在使用的变量是一个字符串。)

Expression<Func<Course, bool>> where = (x => x.SomeNumber == testId);

结果:

exec sp_executesql N'SELECT 
    [Extent1].[CourseId] AS [CourseId], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[SomeNumber] AS [SomeNumber]
    FROM [dbo].[Courses] AS [Extent1]
    WHERE ([Extent1].[SomeNumber] = @p__linq__0) OR (([Extent1].[SomeNumber] IS NULL) AND (@p__linq__0 IS NULL))',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'12'
go

又是 N'12'

当我将列归因于 TypeName="varchar"时,nvarchar(4000) 和 N'12' 变为 varchar(8000) 和 '12'。在第二个示例中,但是在第一个示例中(使用额外的转换)奇怪的是它仍然将参数称为 nvarchar。

在构建表达式时,您能否尝试从项目中删除强制转换。如果需要转换值,请尝试只转换值,而不是实体端属性: IE。

Expression<Func<Documento, bool>> query = (t => t.NumeroDocumento == numeroOriginal);

Expression<Func<Documento, bool>> query = (t => t.NumeroDocumento == numeroOriginal.ToString()); // if numeroOriginal may not be a string.

除此之外,您使用的是哪个版本的 Entity Framework?

关于c# - Entity Framework 从表达式生成错误的参数类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55088202/

相关文章:

c# - 将服务引用添加到 SOAP 服务不会生成异步方法

c# - 何时加载 Generic.xaml 样式?

c# - 当我真的需要继承两个类时如何处理CS1721?

sql - 在查询中提前(或重新排序)重用派生列 - 这是有效的 ANSI SQL 吗?

c# - 如何在构建使用包的 C# 代码期间从 NuGet 包复制文本文件?

sql-server - 将 Unix 文件导入 SQL Server 的最有效和可靠的方法

c# - LINQ to Entities 根据结果拆分字符串

c# - EF代码优先关系的问题

asp.net - 如何强制 Entity Framework 插入标识列?

SQL Server - 如何跨多列创建唯一约束,其中一列是 VARCHAR