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/