C# x、 实体框架不支持ToString()!
实体框架无法识别将路由对象转换为specifix字符串的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
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
的过滤器,