简体   繁体   中英

Entity Framework generating a bad query

I am using EntityFramework 6.3.0 in.Net 4.7.2 I have this code in C#

int userId = 1;
string statusValue = StatusCodes.Failing; // This is a string for anyone wondering, not an Enum
return (from statusRow in DbContext.Statuses
    where statusRow.UserId == userId
          && statusRow.Status == statusValue
          && statusRow.Times > 0
    orderby statusRow.CreatedAtDateTimeOffset descending
    select statusRow).FirstOrDefault();

EntityFramework is generating this query

DECLARE @p__linq__0 int = 1;
DECLARE @p__linq__1 nvarchar = 'Failing';

SELECT TOP (1) 
    [Project1].[Id] AS [Id], 
    [Project1].[UserId] AS [UserId], 
    [Project1].[Times] AS [Times], 
    [Project1].[CreatedAtDateTimeOffset] AS [CreatedAtDateTimeOffset], 
    [Project1].[Status] AS [Status], 
    FROM ( SELECT 
        [Extent1].[Id] AS [Id], 
        [Extent1].[UserId] AS [UserId], 
        [Extent1].[Times] AS [Times], sOverridden], 
        [Extent1].[CreatedAtDateTimeOffset] AS [CreatedAtDateTimeOffset], 
        [Extent1].[Status] AS [Status], 
        FROM [dbo].[Statuses] AS [Extent1]
        WHERE ([Extent1].[UserId] = @p__linq__0) AND (([Extent1].[Status] = @p__linq__1) OR (([Extent1].[Status] IS NULL) AND (@p__linq__1 IS NULL))) AND ([Extent1].[Times] > 0)
    )  AS [Project1]
    ORDER BY [Project1].[CreatedAtDateTimeOffset] DESC

The problem is the second line where it declares p__linq_1. It is setting the type to nvarchar, which sql server then defaults to 1 character in length. Because of this the query returns no records when there are records it should find. The Status column in the model is defined as

[StringLength(50)]
public string Status { get; set; }

[ForeignKey("Status")]
public virtual xStatus StatusValue { get; set; }

I have also tried MaxLength(50) instead of StringLength. But the generated query remains the same.

Anyone know how to fix this?

Update: This may be the same issue as String matching problem in Entity framework. Works for a string literal but not for a string variable

But using string.Compare as specified in that ticket does not work either.


After further debugging on my side I've found that it was a user error on my part and not an issue in Entity Framework.

You can force the type to be varchar instead of nvarchar, using below change:

[Column(TypeName = "VARCHAR")]
[StringLength(50)]
public string Status { get; set; }

With above change the EF query will generate the parameter as varchar .

StringLength appears to be getting ignored. This bit here is perking my interest:

[ForeignKey("Status")]
public virtual xStatus StatusValue { get; set; }

Can you temporarily comment this out, either in whole or the [ForeignKey] attribute? I know this would break anything referencing that StatusValue property expecting an entity, but I might suspect that the PK of this xStatus entity is somehow affecting/overriding the Status column on Statuses. That relationship seems really suspect that there would be some "type" association mapped to this string value rather than via Statuses' PK.

If that fixes the query, check the Status column or PK on this xStatus entity to see if it has a [StringLength] attribute as well.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM