Linq在.Substring()上抛出exception
我有一种情况需要让我的LINQ to Entities查询返回一个子串,具体取决于字符串的长度。 这是查询:
var query = ( from f in Context.Files orderby f.DateAdded descending select new { Concerns = f.Concerns.Name, Sender = f.Sender.Name, CategoryCount = f.Categories.Count(), DateAdded = f.DateAdded, Comment = (f.Comment == null || f.Comment.Length < 5) ? f.Comment : f.Comment }).Take(10);
所以我正在做的是获取最后10个类型为Files的实体,然后从中选择一组属性以显示在listview中。 有些是简单的字符串(Concerns,Sender)。 CategoryCount返回与File对象关联的类别数。
但是,如果注释长于给定长度,我希望注释被截断。 在上面的代码中,一切正常。 现在当我更换这一行时:
Comment = (f.Comment == null || f.Comment.Length < 5) ? f.Comment : f.Comment
有了这条线:
Comment = (f.Comment == null || f.Comment.Length < 5) ? f.Comment : f.Comment.SubString(0,5)
应用程序抛出XamlParseException(???)
在类型’DocumentManager.Views.ListEntriesView’上调用与指定绑定约束匹配的构造函数引发了exception
我真的不知道为什么会这样做。 LINQ中不支持SubString方法吗?
希望有人可以帮助我。 在那之前,我会保持原样。
编辑2(不知何故,我的第一个编辑丢失了。所以我正在重做它):根据我得到的评论,我将我的代码更改为此,现在可以正常工作:
var query = App.Context.Files.OrderByDescending(File => File.DateAdded).Take(10).AsEnumerable() .Select(File => new { Concerns = File.Concerns.Name, Sender = File.Sender.Name, CategoryCount = File.Categories.Count(), DateAdded = File.DateAdded, Comment = (File.Comment == null || File.Comment.Length < 100) ? File.Comment : File.Comment.Substring(0, 100) + "..." });
我忘了提到我正在使用SQLite。 因此,可能在SQLite EF提供程序中未实现Substring。
我不确定,但我怀疑Linq-to-Entities不支持子字符串。 我会将你的Take(10)移到你的select语句之前,然后在Take(10)之后调用AsEnumerable(),之后你的select语句。 这将导致您从数据库中撤回一组文件,然后投影将在内存中完成。
实际上这不是LINQ的错。 您的模型绑定到IQueryable,即您的数据库直接支持的例程(其他所有内容都会抛出exception)。 你应该在某些时候使用AsEnumerable方法来做其他事情。
阅读更多内容,Bill Wagner解释了IQueryable和IEnumerable之间的区别:
这似乎是SQLite解析器中的一个错误,因为
-
子串正常工作以使用LINQ to Entities查询到SQL Server数据库
-
如果查看生成的SQL日志,它会将其生成为Substring SQL函数
-
在SQLite中,正确的函数是substr,而不是substring
因此,生成查询的方式存在错误。
这是修复此错误的方法。
在数据库模型中,在EntityContainer之前添加此代码
在上下文类(在其旁边创建一个分部类)中,添加此代码
[DbFunction("MyModel.Store", "substr")] public string SubStr(string text, int startPos) { return text.Substring(startPos); }
在您的代码中,以这种方式调用Substring
context.SubStr(text, startpos)
它现在将正确映射到SUBSTR函数而不是SUBSTRING! 这就像映射用户定义函数,除了我们映射到现有的标准函数。
希望这可以帮助!
正确 – LINQ不支持子字符串,但是当您尝试这样的事情时,它并不总是非常清楚。