类型 '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
)解决了 int
和 int?
的类似问题,效果很好。但它显然无法实现 Guid
到 string
的转换。
代码如下:
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 else
或 switch
语句
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)))
我正在为 Linq-to-sql
构建表达式树。在数据库中,一些表的相关列存储为 string
,而一些存储为 Guid
。我通过用 Expression.Convert(Expression.Constant(search.PolicyNumber), policyNumberColumnLambda.Type)
包装 lambda 常量(其中 PolicyNumber
有时是 nullable
)解决了 int
和 int?
的类似问题,效果很好。但它显然无法实现 Guid
到 string
的转换。
代码如下:
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 else
或 switch
语句
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)))