使用where子句的3个表LINQ查询

3

这个简单但却恶毒的LINQ查询在运行时给我带来了问题(请注意,只要我不使用JOIN语句,任何适当的where子句都可以工作):

var query = from iDay in db.DateTimeSlot
   join tsk in db.Tasks on iDay.FkTask equals tsk.PkTask
   join dte in db.Mdate on iDay.FkDate equals dte.PkDate
   where dte.Mdate1 == day.ToString(dtForm)
   select new {
      tsk.PkTask,
      tsk.Task,
      iDay.FkTask,
      iDay.TimeSlot,
      iDay.Mdate,
      dte.Mdate1
};

我可以在运行时使where子句生效,但仅适用于db.DateTimeSlot列。否则,如果我删除where子句,则查询有效。如果我尝试使用正确的where子句(即此处列出的),则在尝试foreach遍历var查询结果时会收到“Unhandled Exception: System.ArgumentException: Value does not fall within the expected range”的错误。请注意,当我剥离JOIN子句时,where子句确实有效,当我查询正确的表时。
数据库的模式如下:
tasks -∞ dateTimeSlot ∞- mdate

我正在尝试获取与特定mdate.date相关的任务列表,因此where子句测试mdate.date。
谢谢。
编辑: 这是此部分的Sqlite DB模式:
CREATE TABLE mdate (
  pkDate       INTEGER PRIMARY KEY AUTOINCREMENT,
  mdate        TEXT,
  nDay         TEXT);
CREATE TABLE dateTimeSlot (
  pkDTS        INTEGER PRIMARY KEY AUTOINCREMENT,
  timeSlot     INTEGER,
  fkDate       INTEGER,
  fkTask       INTEGER,

  FOREIGN KEY(fkDate) REFERENCES mdate(pkDate)
  FOREIGN KEY(fkTask) REFERENCES tasks(pkTask));
CREATE TABLE mdate (
  pkDate       INTEGER PRIMARY KEY AUTOINCREMENT,
  mdate        TEXT,
  nDay         TEXT);

编辑: 以下是有效的SQL语句:

sqlite> SELECT tasks.task, mdate.mdate FROM dateTimeSlot
   ...>   INNER JOIN tasks ON dateTimeSlot.fkTask=tasks.pkTask
   ...>   INNER JOIN mdate ON dateTimeSlot.fkDate=mdate.pkDate
   ...>   where mdate.mdate = '2011-07-21';
task|mdate
laundry|2011-07-21
laundry|2011-07-21

编辑: 这是Db.Log = Console.Out的输出结果。请注意,如果保留where子句,则不会出现此SQL垃圾邮件,我只会收到正常的异常调试垃圾邮件:

SELECT tsk$.[pkTask], tsk$.[task], iDay$.[fkTask], iDay$.[timeSlot], t1$.[mdate], t1$.[nDay], t1$.[pkDate], dte$.[mdate]
FROM [main].[dateTimeSlot] AS iDay$
 LEFT JOIN [main].[mdate] AS t1$ ON t1$.[pkDate] = iDay$.[fkDate]
 INNER JOIN [main].[mdate] AS dte$ ON iDay$.[fkDate] = dte$.[pkDate]
 INNER JOIN [main].[tasks] AS tsk$ ON iDay$.[fkTask] = tsk$.[pkTask]
-- Context: SqlServer Model: AttributedMetaModel Build: 4.0.0.0

我在此处发布了完整的错误信息。

问题已解决!我将day.ToString(dtForm)替换为tDate。tDate只是一个本地字符串,等于day.ToString(dtForm)。


1
当您将where子句更改为where dte.Mdate1.ToString() == day.ToString(dtForm)时会发生什么? - David Hoerster
相同的错误,“值不在预期范围内。” dte.Mdate1已经通过智能感知验证为字符串。 - Evan Plumlee
你使用的是哪个 L2S 提供程序?它是否支持带格式的 ToString?尝试设置 db.Log = Console.Out,这样你就可以看到所创建的 SQL。 - user7116
我对SQLite的LINQ to SQL提供程序不是很熟悉,但您能否记录发送到SQLite的内容?将db.Log设置为Console.Out(就像在此博客文章中所示-http://davidhayden.com/blog/dave/archive/2007/08/17/DataContextLogLoggingLINQToSQLOutputConsoleDebuggerOuputWindow.aspx)。也许这可以帮助查明发送到数据库的内容。 - David Hoerster
OP: L2S提供程序是Mono.Data.Sqlite。 - Evan Plumlee
2个回答

2
你的异常输出提示问题是L2S提供程序无法将day.ToString(dtForm)转换为SQLite可以理解的任何形式。
好消息是这基本上是查询的一个固定字符串,不依赖于任何东西。你需要从查询中删除它,但只需将其提取到一个本地变量中即可。
var mdate1 = day.ToString(dtForm);
var query = from iDay in db.DateTimeSlot
   join tsk in db.Tasks on iDay.FkTask equals tsk.PkTask
   join dte in db.Mdate on iDay.FkDate equals dte.PkDate
   where dte.Mdate1 == mdate1
   select new
   {
      tsk.PkTask,
      tsk.Task,
      iDay.FkTask,
      iDay.TimeSlot,
      iDay.Mdate,
      dte.Mdate1
   };

异常的相关部分是 AnalyzeToString,它指向这个方向:
Unhandled Exception: System.ArgumentException: Value does not fall within the expected range.
  at DbLinq.Data.Linq.Sugar.Implementation.ExpressionDispatcher.AnalyzeToString (System.Reflection.MethodInfo method, IList`1 parameters, DbLinq.Data.Linq.Sugar.BuilderContext builderContext) [0x00151] in /var/tmp/portage/dev-lang/mono-2.10.2-r1/work/mono-2.10.2/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/Sugar/Implementation/ExpressionDispatcher.Analyzer.cs:466 
  at DbLinq.Data.Linq.Sugar.Implementation.ExpressionDispatcher.AnalyzeUnknownCall (System.Linq.Expressions.MethodCallExpression expression, IList`1 parameters, DbLinq.Data.Linq.Sugar.BuilderContext builderContext) [0x0008d] in /var/tmp/portage/dev-lang/mono-2.10.2-r1/work/mono-2.10.2/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/Sugar/Implementation/ExpressionDispatcher.Analyzer.cs:345 
  at DbLinq.Data.Linq.Sugar.Implementation.ExpressionDispatcher.AnalyzeCall (System.Linq.Expressions.MethodCallExpression expression, IList`1 parameters, DbLinq.Data.Linq.Sugar.BuilderContext builderContext) [0x00040] in /var/tmp/portage/dev-lang/mono-2.10.2-r1/work/mono-2.10.2/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/Sugar/Implementation/ExpressionDispatcher.Analyzer.cs:178

+1 - 有趣...我正在考虑使用SQLite进行一些工作...记住这点很好。 - David Hoerster

0

Evan:

我想知道day.ToString(dtForm)的值是多少?它是否是1753年1月1日之前的日期?如果是,那么SQL Server将无法接受。


day.ToString(dtForm) 是 2011-07-21,与 Sqlite 数据库中的日期字符串匹配。 - Evan Plumlee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接