C# x、 实体框架不支持ToString()!

C# x、 实体框架不支持ToString()!,c#,.net,entity-framework,linq-to-entities,C#,.net,Entity Framework,Linq To Entities,实体框架无法识别将路由对象转换为specifix字符串的ToString方法: public IEnumerable<Route> GetRoutes(string prefix, string searchPattern, string code) { return Routes. Where(x => code == null || x.Code == code). Where(x => searchPattern == nul

实体框架无法识别将路由对象转换为specifix字符串的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 IEnumerable GetRoutes(字符串前缀、字符串搜索模式、字符串代码)
{
返回路线。
其中(x=>code==null | | x.code==code)。
其中(x=>searchPattern==null | | x.ToString().Contains(searchPattern))。
其中(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();
        }
    }
公共类路由:IDataEntity,ISoftDeletable
{
公共虚拟长Id{get;set;}
公共虚拟字符串代码{get;set;}
公共虚拟布尔被删除{get;set;}
公共虚拟Guid公司ID{get;set;}
公共虚拟IList位置{get;set;}
公共重写字符串ToString()
{
StringBuilder str=新的StringBuilder();
foreach(位置在路线位置)
{
如果(str.Length>0)
{
str.Append(“>”);
}
str.Append(loc.ToString());
}
return str.ToString();
}
}
所有
x.ToString()
都会向实体抛出linq中不支持的异常。。
任何解决方法?

您需要指定需要与
搜索模式
前缀
进行比较的
路由
类的哪个属性。您不能在您的场景中隐式执行
.ToString()

我认为您必须有一个名为
ID
Name
的前缀,您要将其与
搜索模式
进行比较,然后使用:

 .Where(x => searchPattern == null || x.Name.Contains(searchPattern));
因为我想让x演示一个实体,所以,你想如何将实体的名称本身与搜索模式n进行比较

编辑:

看到问题中的更改后,它仍然无法在此查询中使用
ToString()
方法,因为它无法转换为SQL语句

现在,您有两个选择:

第一个:(我不确定是否适用,取决于可疑数据的大小),在调用
Where
扩展之前,尝试使用
ToList()
扩展从数据库加载所有记录。 这应该可以很好地工作,但它可能会导致大型表出现问题

第二个:您必须创建一个存储过程并将逻辑移动到数据库中

实体框架无法识别将路由对象转换为specifix字符串的ToString方法

对。实体框架无法将用c#编写的方法转换为sql

实体框架将表达式转换为sql。有时,这些表达式表示对方法的调用(例如
Queryable.Where
),实体框架知道这些特定的.net Framework方法以及如何将它们转换为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));
}
IQueryable查询=路由
如果(代码!=null)
{
query=query.Where(x=>x.Code==Code)
}
if(searchPattern!=null)
{
query=query.Where(x=>x.Locations.Any(loc=>loc.Name.Contains(searchPattern)))
}
if(前缀!=null)
{
query=query.Where(x=>x.Locations.First().Name.StartsWith(前缀));
}

您不能在客户端执行此操作(
ToString

您必须创建SQL函数,该函数将执行您的计算-它可以只执行位置的字符串连接(我相信它是相关实体),也可以在自定义函数中执行整个测试。然后,您可以将该函数导入实体模型(EDMX),并创建
EdmFunctionAttribute
来调用它-

并可能提供一些帮助。请注意,第二个链接中建议的方法不适用于LINQtoEntities,因为它使用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 );
}
私有静态表达式CreateLike(PropertyInfo属性,字符串值)
{
var参数=表达式参数(typeof(T));
Expression instanceExpression=Expression.MakeMemberAccess(参数,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));
返回表达式.Lambda(like,parameter);
}
ToString()
受较新版本的Entity Framework(从6.1版开始)的支持

参见EF 6.1的第1部分:

EF6.1中有什么内容

EF6.1增加了以下新功能:
[…]

  • 在LINQ查询中支持.ToString、String.Concat和enum HasFlags

(好吧,这个问题已经有几年了,但也许这个信息可以帮助其他人。。。
另请参见相关问题)

请定义
Route
类,以及需要与
searchPattern
prefix
进行比较的类的哪些属性可能有助于提供有关路由的更多信息。请记住,您在实体查询中键入的C代码永远不会执行!相反,表达式树被计算并转换为SQL语句。如何将ToString()转换为SQL?我猜这是因为LinqToEntities无法将您的
ToString
转换为SQL。如果可能的话,您可以首先应用没有
ToString
的过滤器,