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

With UseParameterizedNamesInDynamicQuery, can't compare DateTimeOffset with String #645

Closed
neilbgr opened this issue Nov 14, 2022 · 6 comments
Assignees
Labels

Comments

@neilbgr
Copy link
Contributor

neilbgr commented Nov 14, 2022

1. Description

When UseParameterizedNamesInDynamicQuery = true in config (for best perfs), can not compare DateTimeOffset? with String anymore (even DateTimeOffset).

2. Exception

System.Linq.Dynamic.Core.Exceptions.ParseException
 Message         : Operator '=' incompatible with operand types 'DateTimeOffset?' and 'String'
 StackTrace      :    at System.Linq.Dynamic.Core.Parser.ExpressionParser.CheckAndPromoteOperands(Type signatures, TokenId opId, String opName, Expression& left, Expression& right, Int32 errorPos) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 2084
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseComparisonOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 542
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLogicalAndOrOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 379
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIn() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 297
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAndOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 280
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseOrOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 262
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLambdaOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 242
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseNullCoalescingOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 229
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseConditionalOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 213
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.Parse(Type resultType, Boolean createParameterCtor) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 151
   at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(Type delegateType, ParsingConfig parsingConfig, Boolean createParameterCtor, ParameterExpression[] parameters, Type resultType, String expression, Object[] values) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs:line 121
   at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParsingConfig parsingConfig, Boolean createParameterCtor, ParameterExpression[] parameters, Type resultType, String expression, Object[] values) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs:line 98
   at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParsingConfig parsingConfig, Boolean createParameterCtor, Type itType, Type resultType, String expression, Object[] values) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs:line 357
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Where(IQueryable source, ParsingConfig config, String predicate, Object[] args) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs:line 2651
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Where[TSource](IQueryable`1 source, ParsingConfig config, String predicate, Object[] args) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs:line 2618
   at Program.Main()

3. Fiddle or Project

https://dotnetfiddle.net/UGmC2g

An idea?
Thanks.

@StefH
Copy link
Collaborator

StefH commented Nov 16, 2022

@neilbgr
Thanks for the detailed fiddle project.

The reason why this doesn't work is because the string value is wrapped in a WrappedValue<string> class which cannot be used to compare the value (string) with DateTime of DateTimeOffset.

I'll take a look if this can be fixed, however I think it's difficult.

@StefH StefH self-assigned this Nov 16, 2022
@StefH StefH added the bug label Nov 16, 2022
@StefH
Copy link
Collaborator

StefH commented Feb 4, 2023

@neilbgr
For some reason, the dotnetfiddle throws an error 500.
Can you please post your code here?

@neilbgr
Copy link
Contributor Author

neilbgr commented Feb 4, 2023

// Dynamic LINQ - neilbgr

// @nuget: System.Linq.Dynamic.Core
// @nuget: Z.EntityFramework.Classic

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
using System.Linq.Dynamic.Core;
					
public class Program
{	
	public static void Main()
	{
		GenerateData();
		
		var context = new EntityContext();
		
		var query1 = context.Customers
			.Include(c => c.Location)
			.Where("LastContact = \"2022-11-16\"");
		query1.Dump();
		
		 query1 = context.Customers
			.Include(c => c.Location)
			.Where("Location.UpdateAt = \"2022-11-16\"");
		query1.Dump();
			
		var config = new ParsingConfig
		{
			UseParameterizedNamesInDynamicQuery = true
		};
		try
		{
			var query2 = context.Customers
				.Include(c => c.Location)
				.Where(config, "LastContact = \"2022-11-16\"");
			query2.Dump();
		}
		catch (Exception ex)
		{
			ex.Message.Dump();
		}
			
		try
		{
			var query3 = context.Customers
				.Include(c => c.Location)
				.Where(config, "Location.UpdateAt = \"2022-11-16\"");
			query3.Dump();
		}
		catch (Exception ex)
		{
			ex.Message.Dump();
		}
	}
		 
	public static void GenerateData()
    {
        var list = new List<Customer>();
        list.Add(new Customer()
        {
            Name = "Terri Lee Duffy",
            CompanyName = "ABC",
            City = "Paris",
            Phone = "333-444444",
			Location = new Location() { Name = "test" },     
			LastContact = DateTimeOffset.Parse("2022-11-14")
        });
		list.Add(new Customer()
        {
            Name = "Garry Moore",
            CompanyName = "ABC",
            City = "Paris",
            Phone = "54654-444444",
			Location = new Location() { Name = "ohter test", UpdateAt = DateTimeOffset.Parse("2022-11-16") },     
			LastContact = DateTimeOffset.Parse("2022-11-16")
        });

        using (var context = new EntityContext())
        {
            context.Customers.AddRange(list);
            context.BulkSaveChanges();
        }
	}
	
	public class EntityContext : DbContext
	{
		public EntityContext() : base(FiddleHelper.GetConnectionStringSqlServer())
		{
		}
		
		public DbSet<Customer> Customers { get; set; }
		public DbSet<Location> Locations { get; set; }
	}
	
	public class Customer
    {
        public int CustomerID { get; set; }
        public string Name { get; set; }
        public string CompanyName { get; set; }
        public string City { get; set; }
        public string Phone { get; set; }
		public Location Location { get; set; }
		public DateTimeOffset? LastContact { get; set; }
    }
	
	public class Location
    {
        public int LocationID { get; set; }
        public string Name { get; set; }
		public DateTimeOffset UpdateAt { get; set; }
    }
}

@neilbgr
Copy link
Contributor Author

neilbgr commented Feb 4, 2023

With result:

Dumping object(System.Data.Entity.Infrastructure.DbQuery`1[Customer])
[
   {
   City         : Paris
   CompanyName  : ABC
   CustomerID   : 2
   LastContact  : 11/16/2022 00:00:00 +00:00
   Location     : 
               {
               LocationID  : 2
               Name        : ohter test
               UpdateAt    : 11/16/2022 00:00:00 +00:00
               }
   Name         : Garry Moore
   Phone        : 54654-444444
   }
]Dumping object(System.Data.Entity.Infrastructure.DbQuery`1[Customer])
[
   {
   City         : Paris
   CompanyName  : ABC
   CustomerID   : 2
   LastContact  : 11/16/2022 00:00:00 +00:00
   Location     : 
               {
               LocationID  : 2
               Name        : ohter test
               UpdateAt    : 11/16/2022 00:00:00 +00:00
               }
   Name         : Garry Moore
   Phone        : 54654-444444
   }
]Dumping object(String)
 Operator '=' incompatible with operand types 'DateTimeOffset?' and 'String'
Dumping object(String)
 Operator '=' incompatible with operand types 'DateTimeOffset' and 'String'

@StefH
Copy link
Collaborator

StefH commented Feb 5, 2023

@neilbgr
Thank you for the detailed code. It's fixed.

In some time, a new NuGet will be released.

#666

@StefH StefH closed this as completed Feb 5, 2023
@neilbgr
Copy link
Contributor Author

neilbgr commented Feb 5, 2023

Great! (😅 #666 PR of the beast! 😈)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants