DarkWanderer / ClickHouse.Client

.NET client for ClickHouse
MIT License
315 stars 62 forks source link

cast object of type 'System.DateTime' to type 'System.DateOnly' #345

Open exitxhu opened 1 year ago

exitxhu commented 1 year ago

Hi there is an issue while using DateOnly and try to map the corresponding field in DataReader to that type. I guess DataReader just knows DateTime:

image

as you see the Date column is DateTime in reader (I guess it's a behavior of ado):

image

I think DateOnly should be cast in DateTime then manually recreate DateOnly from that.

from the stack trace its down to this part:

file: ClickHouseDataReader
    public override T GetFieldValue<T>(int ordinal) => (T)GetValue(ordinal);

exception msg: System.InvalidCastException: Unable to cast object of type 'System.DateTime' to type 'System.DateOnly'.

I'd be happy if you have a look at it, or should I pull a request? tnx in advance.

DarkWanderer commented 1 year ago

Hi. How can I reproduce this?

exitxhu commented 1 year ago

Code:

            cmd.CommandText = "select * from Order";
            var r = cmd.ExecuteReader();
            while (r.Read())
            {
                var v = r.GetFieldValue<DateOnly>(1);
            }

Table :

create table test.Order
(
    OrderId Int64,
    Date    Date,
    Amount  Int64
)
    engine = ReplacingMergeTree PARTITION BY toYYYYMM(Date)
        PRIMARY KEY (OrderId, Date)
        ORDER BY (OrderId, Date)
        SETTINGS index_granularity = 8192;

Data: image

EFCore tries to get values by GetFieldValue method of DataReader which is overwritten, for example, dapper has another approach which does the mapping without problem.

StackTrace:

System.InvalidCastException: Unable to cast object of type 'System.DateTime' to type 'System.DateOnly'.
   at ClickHouse.Client.ADO.Readers.ClickHouseDataReader.GetFieldValue[T](Int32 ordinal)
   at EntityFrameworkCore.ClickHouse.TestCases.Controllers.ClickHouseController.Get()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
exitxhu commented 1 year ago

hi again any progress on this?

tnx