实体框架无法识别将路径对象转换为特定字符串的ToString方法:
public IEnumerable<Route> GetRoutes(string prefix, string searchPattern, string code)
{
return Routes.
Where(x => code == null || x.Code == code).
Where(x => searchPattern == null || x.ToString().Contains(searchPattern)).
Where(x => prefix == null || x.ToString().StartsWith(prefix));
}
这是我的路线实体:
public class Route : IDataEntity, ISoftDeletable
{
public virtual long Id { get; set; }
public virtual string Code { get; set; }
public virtual bool IsDeleted { get; set; }
public virtual Guid CompanyId { get; set; }
public virtual IList<LocationInRoute> Locations { get; set; }
public override string ToString()
{
StringBuilder str = new StringBuilder();
foreach (LocationInRoute loc in Locations)
{
if (str.Length > 0)
{
str.Append(" > ");
}
str.Append(loc.ToString());
}
return str.ToString();
}
}
所有x.ToString()
抛出了linq对实体不支持的异常。
任何解决方法?
答案 0 :(得分:2)
实体框架无法识别将路径对象转换为特定字符串的ToString方法。
没错。实体框架无法将您在c#中编写的方法转换为sql。
实体框架将表达式转换为sql。有时这些表达式表示对方法的调用(例如Queryable.Where
),实体框架知道那些特定的.net框架方法以及如何将它们转换为sql。
您希望数据库如何新建一个StringBuilder?
PS:查询中的这个或者标准是一种可怕的方式。您不应该构造一个查询来统治它们。相反,有条件地构造查询:
IQueryable<Route> query = Routes
if (code != null)
{
query = query.Where(x => x.Code == code)
}
if (searchPattern != null)
{
query = query.Where(x => x.Locations.Any(loc => loc.Name.Contains(searchPattern)))
}
if (prefix != null)
{
query = query.Where(x => x.Locations.First().Name.StartsWith(prefix));
}
答案 1 :(得分:2)
您不能在客户端(ToString
)执行此操作。
您必须创建将执行评估的SQL函数 - 它可以只对您的位置进行字符串连接(我相信它是相关实体),或者您可以在自定义函数中执行整个测试。然后,您可以将该函数导入实体模型(EDMX)并创建EdmFunctionAttribute
来调用它 - MSDN。
答案 2 :(得分:1)
您需要指定需要与Route
或searchPattern
进行比较的prefix
课程属性。您不能在您的方案中隐式执行.ToString()
。
答案 3 :(得分:1)
我认为你必须有一个名为ID
或Name
的属性,你要与searchPattern
进行比较,然后使用:
.Where(x => searchPattern == null || x.Name.Contains(searchPattern));
因为我认为x展示了一个实体,所以,你想如何将entiy的名称本身与搜索模式进行比较呢?
修改强>
在看到问题中的更改后,它仍然无法在此查询中使用ToString()
方法,因为它无法转换为SQL语句。
现在,您有两种选择:
第一个:(我不确定是否适用取决于可疑的数据大小),尝试使用ToList()
扩展名从数据库加载所有记录,然后再调用Where
扩展名。
这应该可以正常工作,但它可能会导致巨大的表格出现问题。
第二个:你必须创建一个存储过程并将逻辑移动到数据库。
答案 4 :(得分:1)
ToString()
参见EF 6.1的Release Notes:
EF6.1中的内容
EF6.1增加了以下新功能:
[...]
- 在LINQ查询中支持.ToString,String.Concat和enum HasFlags。
(嗯,问题已经有几年了,但也许这些信息可能有助于其他人...... 另见相关问题How to use ToString SelectListItem with Entity Framework?)
答案 5 :(得分:0)
This post和this post可能会提供一些帮助。请注意,第二个链接中建议的方法不适用于LINQ to Entities,因为它使用ToString。要使其工作,请使用以下命令替换CreateLike方法:
private static Expression<Func<T, bool>> CreateLike<T>( PropertyInfo prop, string value )
{
var parameter = Expression.Parameter( typeof( T ) );
Expression instanceExpression = Expression.MakeMemberAccess( parameter, prop );
if( prop.PropertyType != typeof( System.String ) )
{
var cast = Expression.Convert( instanceExpression, typeof( double? ) );
MethodInfo toString = typeof( SqlFunctions ).GetMethods().First( m => m.Name == "StringConvert" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof( double? ) );
instanceExpression = Expression.Call( toString, cast );
}
var like = Expression.Call( instanceExpression, "Contains", null, Expression.Constant( value, typeof( string ) ) );
return Expression.Lambda<Func<T, bool>>( like, parameter );
}