类型 'System.Guid' 和 'System.String' 之间没有定义强制转换运算符

No coercion operator is defined between types 'System.Guid' and 'System.String'

我正在为 Linq-to-sql 构建表达式树。在数据库中,一些表的相关列存储为 string,而一些存储为 Guid。我通过用 Expression.Convert(Expression.Constant(search.PolicyNumber), policyNumberColumnLambda.Type) 包装 lambda 常量(其中 PolicyNumber 有时是 nullable)解决了 intint? 的类似问题,效果很好。但它显然无法实现 Guidstring 的转换。

代码如下:

public static IQueryable<IRetrieveGuid> SearchByRetrieveGuid<IRetrieveGuid>(this IQueryable<IRetrieveGuid> queryable, SearchModel search)
    {
        var paramLambda = Expression.Parameter(typeof(IRetrieveGuid));
        var columnLambda = Expression.Property(paramLambda, "retrieveguid");
        var lambda = Expression.Lambda<Func<IRetrieveGuid, bool>>(
            Expression.Equal(columnLambda, Expression.Convert(Expression.Constant(search.RetrieveGuid), columnLambda.Type)), paramLambda);
        return queryable.Where(lambda);
    }

如何转换类型以匹配表达式树?

解决方案 1:

这比解决方案 2 快了一个数量级,但是如果您有多种可能性,可能会导致长 if elseswitch 语句

var retrieveGuidAsString =  search.RetrieveGuid.ToString();
var constantLambda = columnLambda.Type.Name == "Guid"  ? Expression.Constant(search.RetrieveGuid) : Expression.Constant(retrieveGuidAsString);
var lambda = Expression.Lambda<Func<IRetrieveGuid, bool>>(Expression.Equal(columnLambda, constantLambda), paramLambda);

解决方案 2:

This did work

public static IQueryable<IRetrieveGuid> SearchByRetrieveGuid<IRetrieveGuid>(this IQueryable<IRetrieveGuid> queryable, SearchModel search)
    {
        var paramLambda = Expression.Parameter(typeof (IRetrieveGuid));
        var columnLambda = Expression.Property(paramLambda, "retrieveguid");
        var lambda = Expression.Lambda<Func<IRetrieveGuid, bool>>(
            Expression.Equal(columnLambda, Expression.Call(Expression.Convert(Expression.Constant(search.RetrieveGuid), typeof (object)), typeof (object).GetMethod("ToString"))), paramLambda);
        return queryable.Where(lambda);
    }

但是速度非常慢,因为它会产生以下 sql

([Extent1].[retrieveguid] = 'c87d1234-46ad-47bf-9a9c-d9a35a454bd5' as uniqueidentifier) AS nvarchar(max))))) OR (([Extent1].[retrieveguid] IS NULL) AND (LOWER( CAST( cast('c87d1234-46ad-47bf-9a9c-d9a35a454bd5' as uniqueidentifier) AS nvarchar(max))) IS NULL)))