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

Entity Class with Enum : long property does not translate into BigInt when using Enum.HasFlag #8538

Closed
ryancyq opened this issue May 22, 2017 · 6 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

@ryancyq
Copy link
Contributor

ryancyq commented May 22, 2017

When a linq to entities query is constructed with an Any clause which compare an entity property of Enum : long against a constant of Enum : long , the entity property does not translate into BigInt.

Exception message:
The data types bigint and numeric are incompatible in the '&' operator
Stack trace:
ERROR 2017-05-22 16:51:00,394 [10   ] Mvc.ExceptionHandling.AbpExceptionFilter - The data types bigint and numeric are incompatible in the '&' operator.
System.Data.SqlClient.SqlException: The data types bigint and numeric are incompatible in the '&' operator.
   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)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, String executeMethod, IReadOnlyDictionary`2 parameterValues, Boolean closeConnection)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable.Enumerator.BufferlessMoveNext(Boolean buffer)
   at Microsoft.EntityFrameworkCore.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](Func`2 operation, Func`2 verifySucceeded, TState state)
   at Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.GetResult[TResult](IEnumerable`1 valueBuffers)
   at lambda_method(Closure , QueryContext )
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass20_0`1.<CompileQueryCore>b__0(QueryContext qc)
   at System.Linq.Queryable.Any[TSource](IQueryable`1 source)
   at Softworkz.Alice.Cases.Assignments.CaseAssignmentManager`1.HasAnyOtherAdminInCase(Int64 caseId, Int64 userId) in C:\data\www\Alice\src\Softworkz.Alice.Core\Cases\Assignments\CaseAssignmentManager.cs:line 287
   at Softworkz.Alice.Cases.Assignments.CaseAssignmentManager.<CheckCreatePermissionAsync>d__5.MoveNext() in C:\data\www\Alice\src\Softworkz.Alice.Core\Cases\Assignments\CaseAssignmentManager.cs:line 92
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Softworkz.Alice.Managers.PermissionDomainManagerBase`2.<CreateAsync>d__17.MoveNext() in C:\data\www\Alice\src\Softworkz.Alice.Core\Managers\PermissionDomainManagerBase.cs:line 72
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Softworkz.Alice.Cases.Assignments.CaseAssignmentManager.<>c__DisplayClass11_0.<<HandleEvent>b__0>d.MoveNext() in C:\data\www\Alice\src\Softworkz.Alice.Core\Cases\Assignments\CaseAssignmentManager.cs:line 216
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException(Task task)
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException(Task task)
   at Nito.AsyncEx.AsyncContext.Run(Func`1 action)
   at Softworkz.Alice.Cases.Assignments.CaseAssignmentManager.HandleEvent(EntityCreatingEventData`1 eventData) in C:\data\www\Alice\src\Softworkz.Alice.Core\Cases\Assignments\CaseAssignmentManager.cs:line 207
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Abp.Domain.Uow.UnitOfWorkInterceptor.PerformSyncUow(IInvocation invocation, UnitOfWorkOptions options)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Abp.Events.Bus.EventBus.Trigger(Type eventType, Object eventSource, IEventData eventData)
   at Abp.Events.Bus.Entities.EntityChangeEventHelper.TriggerEntityChangeEvents(List`1 changedEntities)
   at Abp.Events.Bus.Entities.EntityChangeEventHelper.TriggerEventsInternal(EntityChangeReport changeReport)
   at Abp.Events.Bus.Entities.EntityChangeEventHelper.TriggerEventsAsync(EntityChangeReport changeReport)
   at Abp.EntityFrameworkCore.AbpDbContext.<SaveChangesAsync>d__36.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.<SaveChangesInDbContextAsync>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.<SaveChangesAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Softworkz.Alice.Services.AsyncPermissionCrudAppServiceBase`8.<Create>d__23.MoveNext() in C:\data\www\Alice\src\Softworkz.Alice.Application\Services\AsyncPermissionCrudAppService.cs:line 277
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Abp.Threading.InternalAsyncHelper.<AwaitTaskWithPostActionAndFinallyAndGetResult>d__5`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Abp.Threading.InternalAsyncHelper.<AwaitTaskWithFinallyAndGetResult>d__3`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Softworkz.Alice.Web.Mvc.Controllers.CasesController.<CreateCases>d__8.MoveNext() in C:\data\www\Alice\src\Softworkz.Alice.Web.Mvc\Controllers\CasesController.cs:line 97
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ObjectMethodExecutor.<CastToObject>d__38`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__25.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()
ClientConnectionId:e77d08da-2586-4fa7-9121-cc0d0ffa8aa2

Steps to reproduce

Create an entity class as follows:

[Table("Assignments")]
public class Assignment
{
    public virtual long Id { get; set; }
    public virtual StaticPermission Permissions { get; set; }
}

Create an enum as follows:

[Flags]
public enum StaticPermission : long
{
    NONE = 0x01,
    READ_ONLY= 0x02,
    READ_WRITE= 0x400000000 // 36 bits
}

public static class StaticPermissionExtensions
{
    public const StaticPermission FULL_ACCESS_ALL= StaticPermission.READ_ONLY | StaticPermission.READ_WRITE;
}

Construct a query to check for FULL_ACCESS_ALL

return context.Assignments.Any(a => a.Permissions.HasFlag(StaticPermissionExtensions.FULL_ACCESS_ALL));

The code above thrown the exception stated in the stacktrace.

However, when comparing in the following code, no exception was thrown:

return context.Assignments.Any(a => StaticPermissionExtensions.FULL_ACCESS_ALL.HasFlag(StaticPermissionExtensions.FULL_ACCESS_ALL));

Also, when comparing the entity property against the enum field in the same enum class but with value < 32 bits, no exception was thrown as well.

return context.Assignments.Any(a => a.Permissions.HasFlag(StaticPermission.READ_ONLY));

EF Core version: 1.1.2
Database Provider: Microsoft.EntityFrameworkCore.SqlServer 1.1.2
Operating system:
IDE: Visual Studio 2017

@ajcvickers
Copy link
Member

@rcyq What is the type of the database column?

@ajcvickers
Copy link
Member

@rcyq Also, can you post the SQL that is generated? Or provide a full code listing or project to reproduce what you are seeing?

@ryancyq
Copy link
Contributor Author

ryancyq commented May 23, 2017

The following migration is created after running dotnet ef migrations add "assignment"

migrationBuilder.CreateTable(
    name: "Assignments",
    columns: table => new
    {
        Id = table.Column<long>(nullable: false)
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
        Permissions = table.Column<long>(nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Assignments", x => x.Id);
    });

The sql script generated as follows (using dotnet ef migrations script "assignment")

CREATE TABLE [Assignments] (
    [Id] bigint NOT NULL IDENTITY,
    [Permissions] bigint NOT NULL
);

GO

@ryancyq
Copy link
Contributor Author

ryancyq commented May 23, 2017

I created a sample project which replicates the issue above, Ef Core Sample

You can head over to the "Courses" tab when running the web application which the issue will occur.

@zkost
Copy link

zkost commented Jun 11, 2017

I have the same issue. Can't find any magic dust to get around it.

// My world

  • My SQL table has a column called [status] defined as BigInt.
  • My C# object model has property called [status] defined as Int64. (note: I've tried changing my model property to long and the results are the same.)
  • The purpose of the [status] column/property is to store flags for bitwise operations.

My object model is decorated like so:

   public class Document
    {
...
      [Column(TypeName ="BigInt")]
      public Int64 Status { get; set; }
      // I've tried changing Int64 to a long, a decimal and float - same error 
...
    }

I've tried building my query several different ways and eventually I ended up passing a raw T-SQL statement like this and got the same results. The same error is caused when using a simple Linq Where clause and Pete Montgomery's PredicateBuilder.

// Shortened for brevity - this is all you should need to duplicate the exception
MyContext.MyTable.FromSql(string.Format("select * from [document] where ((Status & {0}) > 0)", (long) requiredFlags));

This also produces the same error:
MyContext.MyTable.FromSql("select * from [document] where ((Status & 0x0008000000000000) > 0)");

I've tried casting the 'requiredFlags' parameter and even the raw value '0x0008000000000000' to a 'numeric' and decimal but Microsoft.EntityFrameworkCore tries to convert it to a numeric every time.

The actual exception is: "System.Data.SqlClient.SqlException: The data types bigint and numeric are incompatible in the '&' operator."

This expression is being converted in EntityFrameworkCore. Please note that this same way of building our expression has been in production for five years. The same code works perfect in TSQL also. This error has manifested itself only after upgrading our code to EntityFrameworkCore.

The exception is thrown in a 'NetStandard 1.4' module (DLL)

Environment

  • Visual Studio 2017 Community (latest patches applied as of 6/10/17)
  • SQL Server 2012
  • All other DLLs and code is referencing the latest nuget available modules. No prerelease code applied.

BTW: I've tested just the netstandard 1.4 module with a test console application and it produces the same error.

Thanks for your help and any suggestions or work around.

@zkost
Copy link

zkost commented Jun 11, 2017

Update: I found the magic dust for at least a temporary solution....

It seams like Linq to Entities doesn't like Int64. Rather then converting it to a long it converts it to a numeric during a query.

When I define my flags as follows (with an Int64) my query produces the exception

   [Flags]
   public enum myFlags : Int64

MyContext.MyTable.FromSql(string.Format("select * from [document] where ((Status & {0}) > 0)", (long) myFlags));

But when I define my flags like this - my query works as expected.

   [Flags]
   public enum myFlags : long

Hope this helps someone.

@smitpatel smitpatel added closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug and removed type-investigation labels Jun 14, 2017
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

4 participants