EF is creating a query that receives a int as parameter. it should be an varchar.
I have this C# code that generates an expression
Expression<Func<Documento, bool>> query = (t => (string)t.NumeroDocumento.ToString() == (string)numeroOriginal.ToString());
var documento = documentoRepository.Obter(query, propriedadesIncluidas: "PapelPessoa.Pessoa");
Documento.Numero documento is a string. The corresponding filed in the database table is a varchar(50). numeroOriginal is also a string.
and this code for the obter (get) in the repository
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();
}
When EF creates the sql query it creates this query(obtained from the 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)
after the parameter is replaced this translates to
SELECT [Extent1].[id] AS [id], [Extent1].[numero_documento] AS [numero_documento],
-- Removed for clariry
FROM [dbo].[DOCUMENTO] AS [Extent1]
WHERE [Extent1].[numero_documento] = 47837
The correct query should be
SELECT [Extent1].[id] AS [id], [Extent1].[numero_documento] AS [numero_documento],
-- Removed for clariry
FROM [dbo].[DOCUMENTO] AS [Extent1]
WHERE [Extent1].[numero_documento] = '47837'
Both work, but the second is much (and i mean MUCH) faster than the first. I ran both in SQL management studio. EF is getting the type of the parameter wrong? How do i fix this? Do I need to change the code or the database? Is my EF configuration for the table wrong?
This is the EF object:
[Table("DOCUMENTO")]
public class Documento : EntidadeBase
{
[Column("numero_documento", TypeName = "varchar")]
[Display(Name = "Numero")]
public string NumeroDocumento { get; set; }
// removed for clarity
}
and this is the table
CREATE TABLE [dbo].[DOCUMENTO](
[id] [int] IDENTITY(1,1) NOT NULL,
[numero_documento] [varchar](50) NULL,
-- removed for clarity
}
I suspect there is something configured a bit different around this entity/column, or possibly the context that is tripping this up. I've tried to reproduce the issue, but I don't come across the same problem:
I added a varchar column to one of my test tables and fed it numeric values to search on.
With the casts same as what you have:
Expression<Func<Course, bool>> where = (x => (string)x.SomeNumber.ToString() == (string)testId.ToString());
I get an SQL statement from EF:
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
the filter reads as N'12'
If I remove the unnecessary casts (the DB column is varchar(50) and the variable being used is a string.)
Expression<Func<Course, bool>> where = (x => x.SomeNumber == testId);
results in:
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
Again, the N'12'
When I attributed the column with TypeName="varchar" then the nvarchar(4000) and N'12' became varchar(8000) and '12'. in the second example, however in the first example (with the extra casting) curiously it still referred to the argument as an nvarchar.
Can you try removing the casting from your project when building the expression. If the value needs to be cast, try only casting the value, and not the entity-side property: Ie
Expression<Func<Documento, bool>> query = (t => t.NumeroDocumento == numeroOriginal);
or
Expression<Func<Documento, bool>> query = (t => t.NumeroDocumento == numeroOriginal.ToString()); // if numeroOriginal may not be a string.
Beyond this, what version of Entity Framework are you using?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.