Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query: | and & operators fail #5930

Closed
AlexBilonog opened this issue Jul 1, 2016 · 8 comments
Closed

Query: | and & operators fail #5930

AlexBilonog opened this issue Jul 1, 2016 · 8 comments
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Milestone

Comments

@AlexBilonog
Copy link

AlexBilonog commented Jul 1, 2016

After I migrated from '1.0.0-rc3-21052' to '1.0.0' I found that the following code fails:

_context.Set<Event>()
    .Where(r => r.EventNo == "1" | r.EventNo == "2")
    .ToList();

// this code also fails:
_context.Set<Event>()
    .Where(r => r.EventNo == "1" & r.EventNo == "2")
    .ToList();

however this code still works fine:

_context.Set<Event>()
    .Where(r => r.EventNo == "1" || r.EventNo == "2")
    .ToList();

_context.Set<Event>()
    .Where(r => r.EventNo == "1" && r.EventNo == "2")
    .ToList();

I cannot use the last one as temporary workaround, because failed code in 3rd party library.

Output:

Compiling query model: 'from Event r in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[EventManager.DataModel.Entities.Event]) where (([r].EventNo == "1") Or ([r].EventNo == "2")) select [r]'
Optimized query model: 'from Event r in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[EventManager.DataModel.Entities.Event]) where (([r].EventNo == "1") Or ([r].EventNo == "2")) select [r]'
TRACKED: True
(QueryContext queryContext) => IEnumerable<Event> _ShapedQuery(
    queryContext: queryContext, 
    shaperCommandContext: SelectExpression: 
        SELECT [r].[ID], [r].[ActualCosts], [r].[Comments], [r].[CompanyID], [r].[CostCenterID], [r].[CreationDateTime], [r].[CreationUser], [r].[CreationUserID], [r].[DepartmentID], [r].[EventNo], [r].[EventTypeVersionID], [r].[FinishDate], [r].[IsAssignAttendeesIndividuallyActual], [r].[IsAssignAttendeesIndividuallyPlanned], [r].[IsBookingSuggestionActualPhase], [r].[IsCancelled], [r].[IsClosed], [r].[IsClosing], [r].[IsCopyAndCancelChildEvent], [r].[IsDeprecated], [r].[IsInActualPhase], [r].[LastChangeDateTime], [r].[LastChangeUserID], [r].[LastModificationDateTime], [r].[LastModificationUser], [r].[Name], [r].[PlannedCosts], [r].[ProjectNumber], [r].[Reason], [r].[RepresenterUserID], [r].[SourceID], [r].[StartDate], [r].[StatusID], [r].[TaxationDate], [r].[VipLoungeDurationDateID], [r].[WasUpdated]
        FROM [Event] AS [r]
        WHERE (([r].[EventNo] = N'1') | ([r].[EventNo] = N'2')) = 1
    , 
    shaper: UnbufferedEntityShaper<Event>
)

Opening connection to database 'XXXXXX' on server 'SQL01'.
Executed DbCommand (32ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [r].[ID], [r].[ActualCosts], [r].[Comments], [r].[CompanyID], [r].[CostCenterID], [r].[CreationDateTime], [r].[CreationUser], [r].[CreationUserID], [r].[DepartmentID], [r].[EventNo], [r].[EventTypeVersionID], [r].[FinishDate], [r].[IsAssignAttendeesIndividuallyActual], [r].[IsAssignAttendeesIndividuallyPlanned], [r].[IsBookingSuggestionActualPhase], [r].[IsCancelled], [r].[IsClosed], [r].[IsClosing], [r].[IsCopyAndCancelChildEvent], [r].[IsDeprecated], [r].[IsInActualPhase], [r].[LastChangeDateTime], [r].[LastChangeUserID], [r].[LastModificationDateTime], [r].[LastModificationUser], [r].[Name], [r].[PlannedCosts], [r].[ProjectNumber], [r].[Reason], [r].[RepresenterUserID], [r].[SourceID], [r].[StartDate], [r].[StatusID], [r].[TaxationDate], [r].[VipLoungeDurationDateID], [r].[WasUpdated]
FROM [Event] AS [r]
WHERE (([r].[EventNo] = N'1') | ([r].[EventNo] = N'2')) = 1

An exception occurred in the database while iterating the results of a query.
System.Data.SqlClient.SqlException (0x80131904): Incorrect syntax near '|'.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, String executeMethod, IReadOnlyDictionary`2 parameterValues, Boolean openConnection, Boolean closeConnection)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues, Boolean manageConnection)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable.Enumerator.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.<_ShapedQuery>d__3`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__15`2.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
ClientConnectionId:3fa56329-072c-46b4-89f1-982d9c5ccaf6
Error Number:102,State:1,Class:15

Further technical details

EF Core version: 1.0.0
Operating system: Windows 8.1
Visual Studio version: 2015 Update 3

@AlexBilonog AlexBilonog changed the title Query: '|' operator fails Query: | and & operators fail Jul 1, 2016
@smitpatel
Copy link
Contributor

Any particular reason to use bitwise operators instead of logical operators on Boolean values?

@AlexBilonog
Copy link
Author

AlexBilonog commented Jul 1, 2016

Thank you for fast reply.
Partially I agree with you. But at the same time partially don't agree.

Reasons:
_1. Some 3rd party libraries can use such operators. Are you 100% sure that major libraries (like Kendo.Mvc, Automapper, etc) don't use such operators? I cannot provide the case from real life.

_2. From C# specification point of view you can use both types (&&, || and &, |). It depends on your style of writing code.
I'm sure that you know the following:
var boolean = true | true; // == true - here it's more a boolean operator
var integer = 1 | 2; // == 3 - here it's a bitwise operator

_3. Developers can by mistake (or by habit) write '&' instead of '&&'. And they don't know about the bug in their code until it occurs in production environment in some cases. It's bad that it's not a compile time error. It increases complexity (developer must keep in mind more dangerous 'cases' that compiler does not track)

_4. Support the code written for EF 6.

_5. Previous release candidates of EF Core (including recent RC2) supported both types of operators. And I don't know any notes in EFCore documentation that you decided to not support such operators.

_6. I know it's not a reason but it doesn't increase complexity in EF Core. You can just use fully the same code as for && and ||.

Thank you in advance!

@smitpatel
Copy link
Contributor

According to https://msdn.microsoft.com/en-us/library/ms176122.aspx
bit wise operators in T-Sql requires the operands to be of specific type. In Sql Server, comparisons are search conditions which are different from values. Therefore the exception is thrown because the Sql generated was incorrect since operands were search conditions instead of supported types.
It is difference between C# & T-Sql which needs to compensated so I asked if it is actually used. I also looked into C# references, in C# | is logical OR if bool operators else bitwise OR. Probably some EF needs to account for.

The reason it worked till RC2 because we added code for translating bitwise operators to Sql after RC2. Previously it was being evaluated on client (in memory) which works fine.

@gdoron
Copy link

gdoron commented Jul 12, 2016

Which library emits expressions with bitwise operators instead of logical and/or?
I've never seen such a library.
Anyway, if indeed there's such library, you should tell them they have a bug.
Can you share the code that emits the expression?

@gdoron
Copy link

gdoron commented Jul 12, 2016

  1. From C# specification point of view you can use both types (&&, || and &, |). It depends on your style of writing code.

From C# point of view, && is boolean operator and & is bitwise operator, it has nothing to do with "style of code".

I'm sure that you know the following:
var boolean = true | true; // == true - here it's more a boolean operator
var integer = 1 | 2; // == 3 - here it's a bitwise operator

This is incorrect, both are bitwise operators, even though bitwise operator on boolean type returns in (C#) a boolean, it's still a bitwise operator.
You can see this dotnet fiddle for example: https://dotnetfiddle.net/m3AQMC . They are not the same thing and don't even behave the same way.

_3. Developers can by mistake (or by habit) write '&' instead of '&&'. And they don't know about the bug in their code until it occurs in production environment in some cases. It's bad that it's not a compile time error. It increases complexity (developer must keep in mind more dangerous 'cases' that compiler does not track)

If code goes production without even testing once it in development or integration environment that's the developers responsibility. It doesn't even give bad results, it throws an exception.

You can't get a compile time error, since it's a valid C# expression. It's no different than using the wrong variable.
BTW, I don't recall ever seeing someone using & and | except from boolean Flags.

@AlexBilonog
Copy link
Author

AlexBilonog commented Jul 12, 2016

I found a dupe of this issue: #6024 (except '|' operator). It was set to 1.1.0 milestone. I think you could close one of two issues. It seems that VB.NET developers prefer to use 'And' operator rather than 'AndAlso'. Just wanted to say that "For bool operands, & computes the logical AND of its operands" (from msdn). And I naturally expected this to work everywhere (in all C# code).

"I don't recall ever seeing someone using & and | except from boolean Flags". I have seen. Especially young developers without C/C++ background. I cannot forbid them (as it's a part of C#, and nowhere is written: "do not use it with bools").

@AlexBilonog
Copy link
Author

AlexBilonog commented Jul 12, 2016

P.S. I agree with you that it would be better, if '&' didn't work with bool values. And I always advise developers to use '&&' instead. And for me it's not an issue now. Just wanted to notify you about changes between rc2 and rtm. I think you could close one of two issues.

@smitpatel smitpatel removed this from the Backlog milestone Jul 26, 2016
@smitpatel
Copy link
Contributor

Cleared milestone. The dupe of this issue was in 1.1.0 milestone and this one was in backlog.

@rowanmiller rowanmiller added this to the 1.1.0 milestone Jul 27, 2016
@smitpatel smitpatel added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Aug 3, 2016
@ajcvickers ajcvickers modified the milestones: 1.1.0-preview1, 1.1.0 Oct 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Projects
None yet
Development

No branches or pull requests

5 participants