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之间的区别:

http://msdn.microsoft.com/en-us/vcsharp/ff963710

这似乎是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不支持子字符串,但是当您尝试这样的事情时,它并不总是非常清楚。