1

我有一个不愿意在 SQLITE 中由 LINQ 处理的表达式。

使用 SQLite 3.8.3.1 使用 SQLite-net 2.1

表达式为:

int stars = location.MinRating;
bool onlyLargePhotos = location.OnlyLargePhotos;

var query = db.MediaItems.Where(x => x.LocationId == location.LocationId && x.Rating >= stars && (!onlyLargePhotos || (onlyLargePhotos && (x.Width >= 2000 || x.Height >= 2000))));

此查询在访问时失败。似乎它在 !onlyLargePhotos 上绊倒了。

例外是:

System.NotSupportedException occurred
  HResult=-2146233067
  Message=Cannot compile: Not
  Source=SQLite.Net
  StackTrace:
       at SQLite.Net.TableQuery`1.CompileExpr(Expression expr, List`1 queryArgs)
       at SQLite.Net.TableQuery`1.CompileExpr(Expression expr, List`1 queryArgs)
       at SQLite.Net.TableQuery`1.CompileExpr(Expression expr, List`1 queryArgs)
       at SQLite.Net.TableQuery`1.GenerateCommand(String selectionList)
       at SQLite.Net.TableQuery`1.Count()
       at SmartFrame.Mosh.DB.WeightedLocationHelper.<>c__DisplayClass9.<CalculateWeightsAsync>b__2(IndexConnection db)
  InnerException: 

另外 - 谁能告诉我是否有办法查看查询将执行什么 SQL?在 SQL LINQ 中,IQueryable 的 ToString() 将显示将要执行的内容。

(顺便说一句:我知道我可以通过创建两个不同的 LINQ 表达式来解决这个问题。但是,我将有更多的排列 - 我要检查更多的字段 - 因此,我不想有 8-16我需要维护的查询 - 我希望由 SQL 引擎完成工作)

4

1 回答 1

4

.net SQLite 包装器并不完美,缺乏许多方法和功能。尤其是 Where 子句。它无法编译某些表达式,因此请尽量编写更简单的表达式。为此,请尝试以下操作:

var query = db.MediaItems.Where(x => x.LocationId == location.LocationId && x.Rating >= stars && (onlyLargePhotos == false || (onlyLargePhotos == true && (x.Width >= 2000 || x.Height >= 2000))));

顺便说一句,为什么需要将变量“onlyLargePhotos”放在 where 中?它不是一个变量,然后可以划分查询。只需将您的位置分成 2 个位置。不用担心性能,where's 将仅按需激活,而不是单独激活,如下所示:

Func<MediaItem, bool> func;
if (onlyLargePhotos)
{
    func = ((x => x.LocationId == location.LocationId && x.Rating >= stars) && ((x.Width >= 2000 || x.Height >= 2000)));
}
else
{
    func = (x => x.LocationId == location.LocationId && x.Rating >= stars);
}

var query = db.MediaItems.Where(func) 

关于生成的SQL,你是看不到的。

于 2014-03-19T11:31:28.410 回答