object must implement iconvertible

Posts   
 
    
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 23-Dec-2013 16:56:26   

Hello

We have some "object must implement iconvertible" errors with the code below.

We can notice that each individual expression is OK. But when they are used in the inline boolean test ( ? : ) it's not OK except when we reach 2 true data base fields.


        private IList<StockForecastProjection> GetDeliveryForecast()  
        {
            LinqMetaData metaData = CreateLinqMetaData();
            var today = DateTime.Today;

            var query =
                from saleDeliveryDetail in metaData.SaleDeliveryDetail
                join saleDelivery in metaData.SaleDelivery on saleDeliveryDetail.FkSaleDeliveryId equals saleDelivery.Id
                join saleOrderDetail in metaData.SaleOrderDetail on saleDeliveryDetail.FkSaleOrderDetailId equals saleOrderDetail.Id
                join item in metaData.Item on saleOrderDetail.FkItemId equals item.Id
                where saleDelivery.FkSaleDeliveryStatusId == (long)SaleDeliveryStatusEnumeration.InProgress
                || saleDelivery.FkSaleDeliveryStatusId == (long)SaleDeliveryStatusEnumeration.Ready

                select new StockForecastProjection
                {
                    ItemId =  saleOrderDetail.FkItemId.Value,
                    Quantity = saleDeliveryDetail.Quantity,
                    //MovementDate = DatabaseFunctions.IfNull(saleDelivery.DeliveryDate, DatabaseFunctions.GetCurrentDate()),                      //KO
                    //MovementDate = (saleDelivery.DeliveryDate.HasValue ? saleDelivery.DeliveryDate.Value : DatabaseFunctions.GetCurrentDate()),   //KO
                    //MovementDate = DatabaseFunctions.IfNull(saleDelivery.DeliveryDate, today),                                                    //KO
                    MovementDate = (saleDelivery.AvailabilityDate.HasValue ? saleDelivery.AvailabilityDate.Value : today),                      //KO
                    //MovementDate = (saleDelivery.DeliveryDate.HasValue ? saleDelivery.DeliveryDate.Value : saleDelivery.AvailabilityDate.Value),  //OK
                    //MovementDate = today,                                                                                                      //OK
                    //MovementDate = DatabaseFunctions.GetCurrentDate(),                                                                            //OK
                    //MovementDate = saleDelivery.DeliveryDate.Value,                                                                              //OK
                    OrderReference = saleDelivery.DeliveryNumber
                };
            return query.ToList<StockForecastProjection>();
        }

We are using * LLBLGen Pro version : 3.5 Final (January 17th, 2013) * Template group + .NET version : Adapter, .NET 3.5 * Database version : MySql 5.0.89

And this is the stack


L'exception System.InvalidCastException n'a pas été gérée par le code utilisateur
  Message="L'objet doit implémenter IConvertible."
  Source="Bejot.Common.Technical"
  StackTrace:
       à Bejot.Common.Technical.ServiceCall.ServiceCallInterceptorBase.CallService(IInvocation invocation) dans c:\SVN\DEV\Bejot.Common\trunk\Bejot.Common.Technical\ServiceCall\ServiceCallInterceptorBase.cs:ligne 72
       à Bejot.Common.Technical.ServiceCall.ServiceCallInterceptorBase.<>c__DisplayClass1.<PerformProceed>b__0() dans c:\SVN\DEV\Bejot.Common\trunk\Bejot.Common.Technical\ServiceCall\ServiceCallInterceptorBase.cs:ligne 54
       à Bejot.Common.Technical.Cache.CacheInterceptor.Execute(IInvocation invocation, ICacheManager cacheManager, ToBeCalledMethod toBeCalledMethod) dans c:\SVN\DEV\Bejot.Common\trunk\Bejot.Common.Technical\Cache\CacheInterceptor.cs:ligne 79
       à Bejot.Common.Technical.ServiceCall.ServiceCallInterceptorBase.PerformProceed(IInvocation invocation) dans c:\SVN\DEV\Bejot.Common\trunk\Bejot.Common.Technical\ServiceCall\ServiceCallInterceptorBase.cs:ligne 53
       à Castle.Core.Interceptor.StandardInterceptor.Intercept(IInvocation invocation)
       à Castle.DynamicProxy.AbstractInvocation.Proceed()
       à Castle.Proxies.IStockServiceProxy.ExportStockForecast()
       à Bejot.Erp.Common.Client.ViewModel.MainViewModelBase.ShowForecastStocks(String printModeAsString) dans c:\SVN\DEV\Bejot.ERP.Common\trunk\Bejot.Erp.Common.Client\ViewModel\Main\MainViewModelBase.cs:ligne 551
       à Bejot.Erp.Common.Client.ViewModel.MainViewModelBase.<get_ShowForecastStocksCommand>b__1d(Object parameter) dans c:\SVN\DEV\Bejot.ERP.Common\trunk\Bejot.Erp.Common.Client\ViewModel\Main\MainViewModelBase.cs:ligne 547
       à Bejot.Common.Client.Core.RelayCommand.Execute(Object parameter) dans c:\SVN\DEV\Bejot.Common\trunk\Bejot.Common.Client\Core\Command\RelayCommand.cs:ligne 64
       à MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated)
       à System.Windows.Documents.Hyperlink.OnClick()
       à System.Windows.Documents.Hyperlink.DispatchNavigation(Object sender)
       à System.Windows.Documents.Hyperlink.DoUserInitiatedNavigation(Object sender)
       à System.Windows.Documents.Hyperlink.OnMouseLeftButtonUp(Object sender, MouseButtonEventArgs e)
       à System.Windows.Documents.Hyperlink.OnMouseLeftButtonUp(MouseButtonEventArgs e)
       à System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
       à System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
       à System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       à System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       à System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       à System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
       à System.Windows.UIElement.CrackMouseButtonEventAndReRaiseEvent(DependencyObject sender, MouseButtonEventArgs e)
       à System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
       à System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
       à System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       à System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       à System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       à System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       à System.Windows.ContentElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
       à System.Windows.Input.InputManager.ProcessStagingArea()
       à System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
       à System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
       à System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
       à System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       à System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       à MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       à MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
       à System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
       à System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
  InnerException: 


daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 24-Dec-2013 07:06:33   

What LLBLGen version and runtime library are you using? ( http://www.llblgen.com/TinyForum/Threads.aspx?ForumID=10 )

What if you try this?

(saleDelivery.AvailabilityDate.HasValue ? saleDelivery.AvailabilityDate : today)

or this:

(saleDelivery.AvailabilityDate ?? today)

... also, it's curious that the stack trace doesn't show anything about linq or llblgen. Can you reproduce it with a small sample using Northwind? Is ithere any generated sql for that query?

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 24-Dec-2013 09:50:30   

(not a solution, just information about the error: the error is caused by the fact a value is used as a parameter value which isn't a real value, e.g. an object is passed as a parameter value, while the value inside the object should have been used as the parameter value. This is often caused by an issue in the linq provider or a badly formulated linq query, so we need some more info to get to the bottom of this simple_smile )

Frans Bouma | Lead developer LLBLGen Pro
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 02-Jan-2014 10:24:32   

Hello daelmo and Otis,

Thanks for your responses.

daelmo wrote:

What LLBLGen version and runtime library are you using? ( http://www.llblgen.com/TinyForum/Threads.aspx?ForumID=10 )

We are using * LLBLGen Pro version : 3.5 Final (January 17th, 2013) * runtime library : 3.5.13.429

daelmo wrote:

What if you try this?

(saleDelivery.AvailabilityDate.HasValue ? saleDelivery.AvailabilityDate : today)

-> doesn't compile (mismatch nullable and not nullable Erreur 4 Impossible de convertir implicitement le type 'System.DateTime?' en 'System.DateTime'. Une conversion explicite existe (un cast est-il manquant ?)

daelmo wrote:

or this:

(saleDelivery.AvailabilityDate ?? today)

-> syntax error Erreur 1 Erreur de syntaxe, ':' attendu

daelmo wrote:

... also, it's curious that the stack trace doesn't show anything about linq or llblgen. Can you reproduce it with a small sample using Northwind? Is ithere any generated sql for that query?

This is the generated sql


140102 10:11:22     117 Query      SELECT `LPA_L3`.`FK_item_Id` AS `ItemId`, `LPA_L1`.`Quantity`, CASE WHEN CASE WHEN ( `LPA_L2`.`AvailabilityDate` IS NOT NULL) THEN 1 ELSE 0 END=1 THEN `LPA_L2`.`AvailabilityDate` ELSE '2014-01-02 00:00:00' END AS `MovementDate`, `LPA_L2`.`DeliveryNumber` AS `OrderReference` FROM (((( `sale_delivery_detail` `LPA_L1`  INNER JOIN `sale_delivery` `LPA_L2`  ON  `LPA_L1`.`FK_sale_delivery_Id` = `LPA_L2`.`Id`) INNER JOIN `sale_order_detail` `LPA_L3`  ON  `LPA_L1`.`FK_sale_order_detail_Id` = `LPA_L3`.`Id`) INNER JOIN `sale_order` `LPA_L4`  ON  `LPA_L3`.`FK_sale_order_Id` = `LPA_L4`.`Id`) INNER JOIN `item` `LPA_L5`  ON  `LPA_L3`.`FK_item_Id` = `LPA_L5`.`Id`) WHERE ( ( ( ( ( ( ( `LPA_L2`.`FK_sale_delivery_status_Id` = 1) OR ( `LPA_L2`.`FK_sale_delivery_status_Id` = 2)) AND ( `LPA_L4`.`FK_third_party_own_company_Id` = 16755))))))

This request returns 6 records in MySQL Query Browser

The error occurs with this code

        private IList<StockForecastProjection> GetDeliveryForecast(long thirdPartyOwnCompanyId)  
        {
            LinqMetaData metaData = CreateLinqMetaData();
            var today = DateTime.Today;

            var query =
                from saleDeliveryDetail in metaData.SaleDeliveryDetail
                join saleDelivery in metaData.SaleDelivery on saleDeliveryDetail.FkSaleDeliveryId equals saleDelivery.Id
                join saleOrderDetail in metaData.SaleOrderDetail on saleDeliveryDetail.FkSaleOrderDetailId equals saleOrderDetail.Id
                join saleOrder in metaData.SaleOrder on saleOrderDetail.FkSaleOrderId equals saleOrder.Id
                join item in metaData.Item on saleOrderDetail.FkItemId equals item.Id
                where 
                (saleDelivery.FkSaleDeliveryStatusId == (long)SaleDeliveryStatusEnumeration.InProgress
                || saleDelivery.FkSaleDeliveryStatusId == (long)SaleDeliveryStatusEnumeration.Ready
                )
                && saleOrder.FkThirdPartyOwnCompanyId == thirdPartyOwnCompanyId

                select new StockForecastProjection
                {
                    ItemId =  saleOrderDetail.FkItemId.Value,
                    Quantity = saleDeliveryDetail.Quantity,
                    //MovementDate = DatabaseFunctions.IfNull(saleDelivery.DeliveryDate, DatabaseFunctions.GetCurrentDate()),                      //KO
                    //MovementDate = (saleDelivery.DeliveryDate.HasValue ? saleDelivery.DeliveryDate.Value : DatabaseFunctions.GetCurrentDate()),   //KO
                    //MovementDate = DatabaseFunctions.IfNull(saleDelivery.DeliveryDate, today),                                                    //KO
                    //MovementDate = (saleDelivery.AvailabilityDate.HasValue ? saleDelivery.AvailabilityDate.Value : today),                        //KO
                    //MovementDate = (saleDelivery.DeliveryDate.HasValue ? saleDelivery.DeliveryDate.Value : saleDelivery.AvailabilityDate.Value),  //OK
                    //MovementDate = today,                                                                                                      //OK
                    //MovementDate = DatabaseFunctions.GetCurrentDate(),                                                                            //OK
                    //MovementDate = saleDelivery.DeliveryDate.Value,                                                                              //OK
                    
                    //MovementDate = saleDelivery.DeliveryDate.Value,   //FIXME en attendant une réponse de LLBLGen
                    MovementDate = (saleDelivery.AvailabilityDate.HasValue ? saleDelivery.AvailabilityDate.Value : today),                      //KO

                    OrderReference = saleDelivery.DeliveryNumber
                };
            return query.ToList<StockForecastProjection>();
        }

on query.ToList

sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 02-Jan-2014 12:57:56   

You will find as an attachment a sample project.

Attachments
Filename File size Added on Approval
IConvertibleTest.LLBLGEN.zip 52,061 02-Jan-2014 12:58.10 Approved
Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 02-Jan-2014 23:33:43   

I highly suspect this has something to do with Castle's Dynamic Proxy. As the exception is not coming from the database, nor from LLBLGen code.

Can you reproduce the same error, without using a Dynamic Proxy?

sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 03-Jan-2014 09:46:27   

Hi Walaa

Thank for your answer. But in the sample we don't use Castle and we have the same issue.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 04-Jan-2014 06:52:54   

I can run your attached project, but I don't know what is the error I should find. No exceptioins thrown and this is the generated SQL:

SELECT `LPLA_1`.`Id`,
       `LPLA_1`.`AvailabilityDate`,
       CASE
         WHEN CASE
                WHEN (`LPLA_1`.`AvailabilityDate` IS NOT NULL) THEN 1
                ELSE 0
              END = 1 THEN `LPLA_1`.`AvailabilityDate`
         ELSE @p2
       END AS `NotNullableAvailabilityDate`
FROM   `sale_delivery` `LPLA_1` 

What is in this test that is wrong?

David Elizondo | LLBLGen Support Team
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 06-Jan-2014 09:45:14   

The SQL query tha tI log on MySQL database is the following :

SELECT
  `LPLA_1`.`Id`,
  `LPLA_1`.`AvailabilityDate`,
  CASE
    WHEN CASE
      WHEN ( `LPLA_1`.`AvailabilityDate` IS NOT NULL) THEN 1
      ELSE 0
      END=1 THEN `LPLA_1`.`AvailabilityDate`
    ELSE '2014-01-06 00:00:00'
  END AS `NotNullableAvailabilityDate`
FROM `sale_delivery`  `LPLA_1`

The error "The object must implement IConvertible" is thrown when calling the ToList() method.

IList<SaleDeliveryProjection> deliveries = query.ToList();

I think this error occurs when the SQL data are converted to objects by LLBLGEN and not when generated the SQL query.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 06-Jan-2014 12:16:07   

How can it be your query contains a constant and our runs don't? ELSE '2014-01-06 00:00:00' suggests the parameter is inlined, and there's no parameter at all. Which is not possible, we don't inline parameter constants.

Frans Bouma | Lead developer LLBLGen Pro
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 06-Jan-2014 13:23:45   

I suppose that the query you added to the thread is the one that LLBLGEN generates. The one I added has been retrieved from a log on MySQL server so...

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 06-Jan-2014 20:56:38   

Well I can see no difference in both SQL queries. So the question is what could be the difference between both tests, that can run successfully at our end and not at your end.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 07-Jan-2014 07:13:03   

The solution you gave us doesn't produce any error. I see that your LLBLGen v3.5 runtime library version are quite old. Please download the latest v3.5 build and reinstall. Before you try again, check that your solution is pointing to the correct v3.5 assemblies. Now try again.

David Elizondo | LLBLGen Support Team
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 07-Jan-2014 10:29:27   

Sorry I don't understand cause I have the latest 3.5 version of LLBLGEN : 3.5 Final (January 17th, 2013).

SD.LLBLGen.Pro.DQE.MySql.NET20 : 3.5.12.1220 SD.LLBLGen.Pro.ORMSupportClasses.NET20 : 3.5.13.429 SD.LLBLGen.Pro.LinqSupportClasses.NET35 : 3.5.13.429 SD.LLBLGen.Pro.QuerySpec : 3.5.12.710

What's wrong with this?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 07-Jan-2014 15:45:27   

those are not the latest builds (see customer area), but the changelog doesn't show any bugfixes in this area, so it should work properly. The thing is that we can't reproduce your issue. I'll give it another go on another machine with the latest builds of v3.5, but if that works too, it's not much we can do. I assume you're using a fairly recent devart mysql connect (use the 'express' one, the one that's free, that's enough to use llblgen with mysql) provider...

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 07-Jan-2014 16:50:34   

I can indeed reproduce it. (on mysql 4.x, older version of devart)

Btw, you reference both devart's provider and mysql's own provider in the test app. Neither are required so you shouldn't reference them in your main app as well.

Very odd. Will look into it.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 07-Jan-2014 17:19:39   

The query

[Test]
public void NullableDateTimeCastTest()
{
    var today = DateTime.Now;

    var metaData = new LinqMetaData(new DataAccessAdapter());
    var q = from o in metaData.Order
            select new
            {
                OrderId = o.OrderId,
                ShippingDate = o.ShippedDate,
                NonNullSD = o.ShippedDate.HasValue ? o.ShippedDate.Value : today
            };
    var results = q.ToList();
    foreach(var v in results)
    {
        if(!v.ShippingDate.HasValue)
        {
            Assert.AreEqual(today.Date, v.NonNullSD.Date);
        }
    }
}

works fine, on sql server, so the sql, the linq query etc. is OK. (results in exactly the same expression tree and compiled lambda which is executed when the projection occurs. )

So I suspect the mysql provider returns a value that's not expected. Looking into it.

(what goes wrong on mysql apparently is that the row of values which is passed into the projection lambda contains a value that's not expected)

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 07-Jan-2014 17:28:30   

Yep, the mysql provider returns a byte array with the value, not a datetime value, for the 3rd field. This is the result of the case statement. I think it's because it doesn't know what type the result value is. At least the mysql devart provider I used (version 7.5).

We can't solve this, as the code is generic, so it can't add a cast implicitly. Now, I did find a workaround:

NotNullableAvailabilityDate = Convert.ToDateTime(saleDelivery.AvailabilityDate.HasValue ? saleDelivery.AvailabilityDate.Value : today)

Notice the Convert.ToDateTime. Normally this is a redundant statement as the value should already be of type DateTime, but here it's adding an explicit cast to DateTime, which will make the ado.net provider return a value of type DateTime, instead of a byte array. Yeah... devart.. disappointed

Hope this helps.

Frans Bouma | Lead developer LLBLGen Pro
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 07-Jan-2014 17:52:18   

OK I understand the matter.

Thanks for the workaround.

I close the thread.