[英]Entity Framework generating wrong parameter type from expression
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也是一个字符串。
这个代码用于存储库中的obter(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查询时,它会创建此查询(从debbuger获取)
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。
您可以在构建表达式时尝试从项目中删除转换。 如果需要转换值,请尝试仅转换值,而不是实体端属性:即
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?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.