Index: System.Data.SQLite.Linq/Resources/SQLiteProviderServices.ProviderManifest.xml ================================================================== --- System.Data.SQLite.Linq/Resources/SQLiteProviderServices.ProviderManifest.xml +++ System.Data.SQLite.Linq/Resources/SQLiteProviderServices.ProviderManifest.xml @@ -688,10 +688,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: System.Data.SQLite.Linq/SQL Generation/SqlGenerator.cs ================================================================== --- System.Data.SQLite.Linq/SQL Generation/SqlGenerator.cs +++ System.Data.SQLite.Linq/SQL Generation/SqlGenerator.cs @@ -316,10 +316,12 @@ functionHandlers.Add("CONCAT", HandleConcatFunction); functionHandlers.Add("DATEPART", HandleDatepartDateFunction); functionHandlers.Add("DatePart", HandleDatepartDateFunction); functionHandlers.Add("GETDATE", HandleGetDateFunction); functionHandlers.Add("GETUTCDATE", HandleGetUtcDateFunction); + functionHandlers.Add("TOLOCALTIME", HandleToLocalTimeFunction); + functionHandlers.Add("TOUNIVERSALTIME", HandleToUniversalTimeFunction); return functionHandlers; } /// /// All special non-aggregate canonical functions and their handlers @@ -2660,17 +2662,24 @@ Debug.Assert(e.Arguments.Count == 0, "Canonical getdate function should have no arguments"); switch (sqlgen._manifest._dateFormat) { case SQLiteDateFormats.Ticks: - result.Append("(STRFTIME('%s', 'now') * 10000000 + 621355968000000000)"); + result.Append("(STRFTIME('%s', 'now', 'localtime') * 10000000 + 621355968000000000)"); break; case SQLiteDateFormats.JulianDay: - result.Append("CAST(STRFTIME('%J', 'now') AS double)"); + result.Append("CAST(STRFTIME('%J', 'now', 'localtime') AS double)"); + break; + case SQLiteDateFormats.UnixEpoch: + result.Append("STRFTIME('%s', 'now', 'localtime')"); + break; + case SQLiteDateFormats.InvariantCulture: + case SQLiteDateFormats.CurrentCulture: + result.Append("STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'now', 'localtime')"); break; default: - result.Append("STRFTIME('%Y-%m-%d %H:%M:%S', 'now')"); + result.Append("STRFTIME('%Y-%m-%d %H:%M:%S', 'now', 'localtime')"); break; } return result; } @@ -2681,22 +2690,85 @@ Debug.Assert(e.Arguments.Count == 0, "Canonical getutcdate function should have no arguments"); switch (sqlgen._manifest._dateFormat) { case SQLiteDateFormats.Ticks: - result.Append("(STRFTIME('%s', 'now', 'utc') * 10000000 + 621355968000000000)"); + result.Append("(STRFTIME('%s', 'now') * 10000000 + 621355968000000000)"); break; case SQLiteDateFormats.JulianDay: - result.Append("CAST(STRFTIME('%J', 'now', 'utc') AS double)"); + result.Append("CAST(STRFTIME('%J', 'now') AS double)"); + break; + case SQLiteDateFormats.UnixEpoch: + result.Append("STRFTIME('%s', 'now')"); + break; + case SQLiteDateFormats.InvariantCulture: + case SQLiteDateFormats.CurrentCulture: + result.Append("STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'now')"); break; default: - result.Append("STRFTIME('%Y-%m-%d %H:%M:%S', 'now', 'utc')"); + result.Append("STRFTIME('%Y-%m-%d %H:%M:%S', 'now')"); break; } return result; } + + private static ISqlFragment HandleToUniversalTimeFunction(SqlGenerator sqlgen, DbFunctionExpression e) + { + SqlBuilder result = new SqlBuilder(); + Debug.Assert(e.Arguments.Count == 1, "Canonical touniversaltime function should have exactly one argument"); + + switch (sqlgen._manifest._dateFormat) + { + case SQLiteDateFormats.Ticks: + result.Append(String.Format("(STRFTIME('%s', {0}, 'utc') * 10000000 + 621355968000000000)", e.Arguments[0].Accept(sqlgen))); + break; + case SQLiteDateFormats.JulianDay: + result.Append(String.Format("CAST(STRFTIME('%J', {0}, 'utc') AS double)", e.Arguments[0].Accept(sqlgen))); + break; + case SQLiteDateFormats.UnixEpoch: + result.Append(String.Format("STRFTIME('%s', {0}, 'utc')", e.Arguments[0].Accept(sqlgen))); + break; + case SQLiteDateFormats.InvariantCulture: + case SQLiteDateFormats.CurrentCulture: + result.Append(String.Format("STRFTIME('%Y-%m-%dT%H:%M:%fZ', {0}, 'utc')", e.Arguments[0].Accept(sqlgen))); + break; + default: + result.Append(String.Format("STRFTIME('%Y-%m-%d %H:%M:%S', {0}, 'utc')", e.Arguments[0].Accept(sqlgen))); + break; + } + + return result; + } + + private static ISqlFragment HandleToLocalTimeFunction(SqlGenerator sqlgen, DbFunctionExpression e) + { + SqlBuilder result = new SqlBuilder(); + Debug.Assert(e.Arguments.Count == 1, "Canonical tolocaltime function should have exactly one argument"); + + switch (sqlgen._manifest._dateFormat) + { + case SQLiteDateFormats.Ticks: + result.Append(String.Format("(STRFTIME('%s', {0}, 'localtime') * 10000000 + 621355968000000000)", e.Arguments[0].Accept(sqlgen))); + break; + case SQLiteDateFormats.JulianDay: + result.Append(String.Format("CAST(STRFTIME('%J', {0}, 'localtime') AS double)", e.Arguments[0].Accept(sqlgen))); + break; + case SQLiteDateFormats.UnixEpoch: + result.Append(String.Format("STRFTIME('%s', {0}, 'localtime')", e.Arguments[0].Accept(sqlgen))); + break; + case SQLiteDateFormats.InvariantCulture: + case SQLiteDateFormats.CurrentCulture: + result.Append(String.Format("STRFTIME('%Y-%m-%dT%H:%M:%fZ', {0}, 'localtime')", e.Arguments[0].Accept(sqlgen))); + break; + default: + result.Append(String.Format("STRFTIME('%Y-%m-%d %H:%M:%S', {0}, 'localtime')", e.Arguments[0].Accept(sqlgen))); + break; + } + + return result; + } /// /// Handles special case in which datepart 'type' parameter is present. all the functions /// handles here have *only* the 1st parameter as datepart. datepart value is passed along /// the QP as string and has to be expanded as TSQL keyword. @@ -2742,10 +2814,13 @@ switch (sqlgen._manifest._dateFormat) { case SQLiteDateFormats.Ticks: result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[1].Accept(sqlgen))); break; + case SQLiteDateFormats.UnixEpoch: + result.Append(String.Format("{0}, 'unixepoch'", e.Arguments[1].Accept(sqlgen))); + break; default: result.Append(e.Arguments[1].Accept(sqlgen)); break; } @@ -2758,10 +2833,13 @@ switch (sqlgen._manifest._dateFormat) { case SQLiteDateFormats.Ticks: result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[1].Accept(sqlgen))); break; + case SQLiteDateFormats.UnixEpoch: + result.Append(String.Format("{0}, 'unixepoch'", e.Arguments[1].Accept(sqlgen))); + break; default: result.Append(e.Arguments[1].Accept(sqlgen)); break; } @@ -2788,10 +2866,13 @@ result.Append(String.Format("(STRFTIME('%s', JULIANDAY({1}) + ({0} / 86400.0)) * 10000000 + 621355968000000000)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen))); break; case SQLiteDateFormats.JulianDay: result.Append(String.Format("CAST(STRFTIME('%J', JULIANDAY({1}) + ({0} / 86400.0)) AS double)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen))); break; + case SQLiteDateFormats.UnixEpoch: + result.Append(String.Format("(STRFTIME('%s', JULIANDAY({1}) + ({0} / 86400.0)))", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen))); + break; default: result.Append(String.Format("STRFTIME('%Y-%m-%d %H:%M:%S', JULIANDAY({1}) + ({0} / 86400.0))", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen))); break; } @@ -2812,10 +2893,13 @@ switch (sqlgen._manifest._dateFormat) { case SQLiteDateFormats.Ticks: result.Append(String.Format("CAST((({0} - 621355968000000000) / 10000000.0) - (({1} - 621355968000000000) / 10000000.0) * 86400.0 AS integer)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen))); break; + case SQLiteDateFormats.UnixEpoch: + result.Append(String.Format("CAST(({0} - {1}) * 86400.0 AS integer)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen))); + break; default: result.Append(String.Format("CAST((JULIANDAY({1}) - JULIANDAY({0})) * 86400.0 AS integer)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen))); break; } @@ -2848,10 +2932,13 @@ switch (sqlgen._manifest._dateFormat) { case SQLiteDateFormats.Ticks: result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[0].Accept(sqlgen))); break; + case SQLiteDateFormats.UnixEpoch: + result.Append(String.Format("{0}, 'unixepoch'", e.Arguments[0].Accept(sqlgen))); + break; default: result.Append(e.Arguments[0].Accept(sqlgen)); break; } Index: System.Data.SQLite.Linq/SQLiteProviderManifest.cs ================================================================== --- System.Data.SQLite.Linq/SQLiteProviderManifest.cs +++ System.Data.SQLite.Linq/SQLiteProviderManifest.cs @@ -37,10 +37,19 @@ } internal static XmlReader GetProviderManifest() { return GetXmlResource("System.Data.SQLite.Linq.Resources.SQLiteProviderServices.ProviderManifest.xml"); + } + + /// + /// Returns or sets the date/time format in use for this instance. + /// + internal SQLiteDateFormats DateTimeFormat + { + get { return _dateFormat; } + set { _dateFormat = value; } } /// /// Returns manifest information for the provider /// Index: System.Data.SQLite/SQLite3.cs ================================================================== --- System.Data.SQLite/SQLite3.cs +++ System.Data.SQLite/SQLite3.cs @@ -406,11 +406,11 @@ if (n > 0) throw new SQLiteException(n, SQLiteLastError()); } internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt) { - byte[] b = ToUTF8(dt); + byte[] b = ToBindUTF8(dt); int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1)); if (n > 0) throw new SQLiteException(n, SQLiteLastError()); } internal override void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData) Index: System.Data.SQLite/SQLiteConnection.cs ================================================================== --- System.Data.SQLite/SQLiteConnection.cs +++ System.Data.SQLite/SQLiteConnection.cs @@ -1000,10 +1000,33 @@ throw new InvalidOperationException("Database connection not valid for getting number of changes."); return _sql.Changes; } } + + /// + /// Returns or sets the date/time format currently in use for this connection. + /// +#if !PLATFORM_COMPACTFRAMEWORK + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] +#endif + public SQLiteDateFormats DateTimeFormat + { + get { + if (_sql == null) + throw new InvalidOperationException("Database connection not valid for getting date/time format."); + + return _sql.DateTimeFormat; + } + set + { + if (_sql == null) + throw new InvalidOperationException("Database connection not valid for setting date/time format."); + + _sql.DateTimeFormat = value; + } + } /// /// Returns the version of the underlying SQLite database engine /// public static string SQLiteVersion Index: System.Data.SQLite/SQLiteConvert.cs ================================================================== --- System.Data.SQLite/SQLiteConvert.cs +++ System.Data.SQLite/SQLiteConvert.cs @@ -22,10 +22,15 @@ /// The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC). /// private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + /// + /// The most complete human-readable time string format natively understood by SQLite. + /// + private const string BindFormat = "yyyy-MM-ddTHH:mm:ss.fff"; + /// /// The format string for DateTime values when using the InvariantCulture or CurrentCulture formats. /// private const string FullFormat = "yyyy-MM-ddTHH:mm:ss.fffffffK"; @@ -66,10 +71,21 @@ /// The default date/time format to use for this instance internal SQLiteConvert(SQLiteDateFormats fmt) { _datetimeFormat = fmt; } + + #region Public Properties + /// + /// Returns or sets the date/time format currently in use for this instance. + /// + public SQLiteDateFormats DateTimeFormat + { + get { return _datetimeFormat; } + set { _datetimeFormat = value; } + } + #endregion #region UTF-8 Conversion Functions /// /// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character. /// @@ -98,10 +114,24 @@ /// The UTF-8 encoded string, including a 0 terminating byte at the end of the array. public byte[] ToUTF8(DateTime dateTimeValue) { return ToUTF8(ToString(dateTimeValue)); } + + /// + /// Convert a DateTime to a UTF-8 encoded, zero-terminated byte array. + /// + /// + /// This function is a convenience function, which first calls ToBindString() on the DateTime, and then calls ToUTF8() with + /// the string result. + /// + /// The DateTime to convert. + /// The UTF-8 encoded string, including a 0 terminating byte at the end of the array. + public byte[] ToBindUTF8(DateTime dateTimeValue) + { + return ToUTF8(ToBindString(dateTimeValue)); + } /// /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string /// /// The pointer to the memory where the UTF-8 string is encoded @@ -159,10 +189,20 @@ /// culture-independent formatted date and time string, a formatted date and time string in the current /// culture, or an ISO8601-format string. /// A DateTime value public DateTime ToDateTime(string dateText) { + // + // NOTE: First, try to interpret the string as a correctly formatted date. + // + DateTime result; + + if (DateTime.TryParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out result)) + { + return result; + } + switch (_datetimeFormat) { case SQLiteDateFormats.Ticks: return new DateTime(Convert.ToInt64(dateText, CultureInfo.InvariantCulture)); case SQLiteDateFormats.JulianDay: @@ -195,10 +235,20 @@ /// The JulianDay value the Datetime represents public double ToJulianDay(DateTime value) { return value.ToOADate() + 2415018.5; } + + /// + /// Converts a DateTime to a string value suitable for binding to a query parameter. + /// + /// The DateTime value to convert + /// An ISO8601 formatted date/time string in the invariant culture. + public string ToBindString(DateTime dateValue) + { + return dateValue.ToString(BindFormat, CultureInfo.InvariantCulture); + } /// /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened. /// /// The DateTime value to convert Index: Tests/basic.eagle ================================================================== --- Tests/basic.eagle +++ Tests/basic.eagle @@ -740,14 +740,14 @@ unset -nocomplain name rows result db fileName } -constraints {eagle monoBug28 command.sql compile.DATA System.Data.SQLite} \ -result [subst {{1 {{x 1} {y2 {Wednesday, 16 December 2009}}}} {2 {{x 2} {y2\ 12:00:00}}} {3 {{x 3} {y2 {Wednesday, 16 December 2009 12:00:00}}}} {4 {{x 4}\ {y2 12/16/2009}}} {5 {{x 5} {y2 12:00}}} {6 {{x 6} {y2 {12/16/2009 12:00}}}} {7\ -{{x 7} {y2 2009-12-16T00:00:00.0000000Z}}} {8 {{x 8} {y2\ -${date}T12:00:00.0000000Z}}} {9 {{x 9} {y2 2009-12-16T12:00:00.0000000Z}}}\ -{10 {{x 10} {y2 2009-12-16T00:00:00.0000000Z}}} {11 {{x 11} {y2\ -${date}T12:00:00.0000000Z}}} {12 {{x 12} {y2 2009-12-16T12:00:00.0000000Z}}}}]} +{{x 7} {y2 2009-12-16T00:00:00.000}}} {8 {{x 8} {y2\ +${date}T12:00:00.000}}} {9 {{x 9} {y2 2009-12-16T12:00:00.000}}} {10 {{x 10}\ +{y2 2009-12-16T00:00:00.000}}} {11 {{x 11} {y2 ${date}T12:00:00.000}}} {12 {{x\ +12} {y2 2009-12-16T12:00:00.000}}}}]} ############################################################################### runTest {test basic-1.14 {DateTime using current culture} -setup { setupDb [set fileName basic-1.14.db] "" "" "DateTimeFormat=CurrentCulture;" @@ -801,14 +801,70 @@ } -constraints \ {eagle culture.en_US monoBug28 command.sql compile.DATA System.Data.SQLite} \ -result [subst {{1 {{x 1} {y2 {Wednesday, 16 December 2009}}}} {2 {{x 2} {y2\ 12:00:00}}} {3 {{x 3} {y2 {Wednesday, 16 December 2009 12:00:00}}}} {4 {{x 4}\ {y2 12/16/2009}}} {5 {{x 5} {y2 12:00}}} {6 {{x 6} {y2 {12/16/2009 12:00}}}} {7\ -{{x 7} {y2 2009-12-16T00:00:00.0000000Z}}} {8 {{x 8} {y2\ -${date}T12:00:00.0000000Z}}} {9 {{x 9} {y2 2009-12-16T12:00:00.0000000Z}}}\ -{10 {{x 10} {y2 2009-12-16T00:00:00.0000000Z}}} {11 {{x 11} {y2\ -${date}T12:00:00.0000000Z}}} {12 {{x 12} {y2 2009-12-16T12:00:00.0000000Z}}}}]} +{{x 7} {y2 2009-12-16T00:00:00.000}}} {8 {{x 8} {y2\ +${date}T12:00:00.000}}} {9 {{x 9} {y2 2009-12-16T12:00:00.000}}} {10 {{x 10}\ +{y2 2009-12-16T00:00:00.000}}} {11 {{x 11} {y2 ${date}T12:00:00.000}}} {12 {{x\ +12} {y2 2009-12-16T12:00:00.000}}}}]} + +############################################################################### + +runTest {test basic-1.15 {other date/time functions for LINQ} -setup { + set formats [list Ticks ISO8601 JulianDay UnixEpoch \ + InvariantCulture CurrentCulture] + + # 1996-07-04 00:00:00|1996-08-01 00:00:00 + # 1998-05-06 00:00:00|1998-06-03 00:00:00 + # 11078|ALFKI|1|2003-01-02 04:05:06.789| + # 2009-08-07 06:05:04.321|1999-12-25 23:59:42.654|0|||||| + + set prefix "SELECT VALUE o FROM Orders AS o WHERE" + + set queries [list \ + "SQLite.GetDate() >= SQLite.ToLocalTime(@dt) AND o.OrderID = 11078;" \ + "SQLite.GetUtcDate() >= @dt AND o.OrderID = 11078;" \ + "Year(SQLite.GetDate()) == Year(@dt) AND o.OrderID = 11078;" \ + "Month(SQLite.GetDate()) == Month(@dt) AND o.OrderID = 11078;" \ + "Day(SQLite.GetDate()) == Day(@dt) AND o.OrderID = 11078;" \ + "Hour(o.OrderDate) == 4 AND o.OrderID = 11078;" \ + "Minute(o.OrderDate) == 5 AND o.OrderID = 11078;" \ + "Second(o.OrderDate) == 6 AND o.OrderID = 11078;"] +} -body { + set result [list] + + foreach format $formats { + foreach query $queries { + set code [catch { + testExec $testLinqExeFile [list -eventflags Wait -directory \ + [file dirname $testLinqExeFile] -nocarriagereturns -stdout output \ + -success 0] -dateTime [appendArgs \" $format \"] [appendArgs \" \ + $prefix " " $query \"] [appendArgs \" \ + [expr {[string first @dt $query] != -1 ? $date : ""}] \"] + } error] + + tlog "---- BEGIN STDOUT OUTPUT\n" + tlog $output + tlog "\n---- END STDOUT OUTPUT\n" + + lappend result $code + + if {$code == 0} then { + lappend result [string trim $output] + } else { + lappend result [string trim $error] + } + } + } + + set result +} -cleanup { + unset -nocomplain prefix format formats query queries + unset -nocomplain code output error result +} -constraints {eagle file_testlinq.exe file_northwindEF.db} \ +-result {}} ############################################################################### unset -nocomplain date Index: Tests/testlinq.out ================================================================== --- Tests/testlinq.out +++ Tests/testlinq.out @@ -1860,10 +1860,11 @@ 05033 1734 1204 13008 87110 + Chai Chang Chef Anton's Cajun Seasoning Chef Anton's Gumbo Mix Uncle Bob's Organic Dried Pears Index: testlinq/Program.cs ================================================================== --- testlinq/Program.cs +++ testlinq/Program.cs @@ -1,9 +1,11 @@ using System; using System.Diagnostics; -using System.Linq; +using System.Linq; +using System.Data.EntityClient; using System.Data.Objects; +using System.Data.SQLite; using System.Text; using System.Transactions; namespace testlinq { @@ -48,11 +50,11 @@ } case "skip": { int pageSize = 0; - if (args.Length > 1) + if ((args.Length > 1) && !String.IsNullOrEmpty(args[1])) { arg = args[1]; if (arg != null) pageSize = int.Parse(arg.Trim()); @@ -90,11 +92,11 @@ } case "eftransaction": { bool value = false; - if (args.Length > 1) + if ((args.Length > 1) && !String.IsNullOrEmpty(args[1])) { if (!bool.TryParse(args[1], out value)) { Console.WriteLine( "cannot parse \"{0}\" as boolean", @@ -104,10 +106,62 @@ } } return EFTransactionTest(value); } + case "datetime": + { + SQLiteDateFormats dateTimeFormat = SQLiteDateFormats.Default; + string queryString = null; + DateTime? dateTime = null; + + if ((args.Length > 1) && !String.IsNullOrEmpty(args[1])) + { + try + { + dateTimeFormat = (SQLiteDateFormats)Enum.Parse( + typeof(SQLiteDateFormats), args[1], true); + } + catch + { + Console.WriteLine( + "cannot parse \"{0}\" as a date/time format", + args[1]); + + return 1; + } + } + + if (args.Length > 2) + { + queryString = args[2]; + + if (queryString != null) + queryString = queryString.Trim(); + } + + if ((args.Length > 3) && !String.IsNullOrEmpty(args[3])) + { + DateTime dateTimeValue; + + if (DateTime.TryParse(args[3], out dateTimeValue)) + { + dateTime = DateTime.SpecifyKind( + dateTimeValue, DateTimeKind.Utc); + } + else + { + Console.WriteLine( + "cannot parse \"{0}\" as a date/time", + args[3]); + + return 1; + } + } + + return DateTimeTest(dateTimeFormat, queryString, dateTime); + } default: { Console.WriteLine("unknown test \"{0}\"", arg); return 1; } @@ -285,10 +339,63 @@ once = true; } } } + + return 0; + } + + // + // NOTE: Used to test the various DateTime methods. + // + private static int DateTimeTest( + SQLiteDateFormats dateTimeFormat, + string queryString, + DateTime? dateTime + ) + { + using (northwindEFEntities db = new northwindEFEntities()) + { + EntityConnection connection = db.Connection as EntityConnection; + + if (connection == null) + { + Console.WriteLine("not an entity connection"); + return 1; + } + + SQLiteConnection storeConnection = + connection.StoreConnection as SQLiteConnection; + + if (storeConnection == null) + { + Console.WriteLine("not a SQLite store connection"); + return 1; + } + + connection.Open(); /* NOTE: Force open now. */ + storeConnection.DateTimeFormat = dateTimeFormat; + + bool once = false; + + ObjectParameter[] parameters = (dateTime != null) ? + new ObjectParameter[] { new ObjectParameter("dt", dateTime) } : + new ObjectParameter[] { }; + + var query = db.CreateQuery(queryString, parameters); + + foreach (Orders orders in query) + { + if (once) + Console.Write(' '); + + Console.Write(orders.OrderID); + + once = true; + } + } return 0; } private static int OldTests() Index: testlinq/northwindEF.db ================================================================== --- testlinq/northwindEF.db +++ testlinq/northwindEF.db cannot compute difference between binary files Index: testlinq/testlinq.2008.csproj ================================================================== --- testlinq/testlinq.2008.csproj +++ testlinq/testlinq.2008.csproj @@ -48,10 +48,16 @@ + + + {AC139952-261A-4463-B6FA-AEBC25283A66} + System.Data.SQLite.2008 + + True True NorthwindModel2008.edmx Index: testlinq/testlinq.2010.csproj ================================================================== --- testlinq/testlinq.2010.csproj +++ testlinq/testlinq.2010.csproj @@ -45,10 +45,16 @@ + + + {AC139952-261A-4463-B6FA-AEBC25283A66} + System.Data.SQLite.2010 + + True True