TypeName_SQLiteProviderServices |
If this environment variable is set [to anything], it will be
used by the System.Data.SQLite.SQLiteFactory class as the type name
containing the System.Data.Common.DbProviderServices implementation
Index: Doc/Extra/Provider/version.html
==================================================================
--- Doc/Extra/Provider/version.html
+++ Doc/Extra/Provider/version.html
@@ -53,10 +53,13 @@
In the SQLiteDataReader.VerifyType method, remove duplicate "if" statement for the DbType.SByte value and move the remaining "if" to the Int64 affinity. Fix for [c5cc2fb334]. ** Potentially Incompatible Change **
Handle Julian Day values that fall outside of the supported range for OLE Automation dates. Fix for [3e783eecbe]. ** Potentially Incompatible Change **
Make sure the interop files are copied when publishing a project that refers to a NuGet package containing them. Fix for [e796ac82c1]. ** Potentially Incompatible Change **
Make sure the interop files are copied before the PostBuildEvent. Fix for [f16c93a932]. ** Potentially Incompatible Change **
Modify GetSchemaTable method to avoid setting SchemaTableColumn.IsKey column to true when more than one table is referenced. Fix for [47c6fa04d3]. ** Potentially Incompatible Change **
+ Add AppendManifestToken_SQLiteProviderManifest environment variable to enable better integration between LINQ and the underlying store connection.
+ Add SQLite_ForceLogPrepare environment variable to force logging of all prepared SQL regardless of the flags for the associated connection.
+ Honor the DateTimeFormat, DateTimeKind, DateTimeFormatString, BinaryGUID connection string and/or provider manifest token properties from within the LINQ assembly. Fix for [8d928c3e88]. ** Potentially Incompatible Change **
1.0.94.0 - September 9, 2014
- Updated to SQLite 3.8.6.
- Updated to Entity Framework 6.1.1.
Index: System.Data.SQLite.Linq/Resources/SQLiteProviderServices.StoreSchemaDefinition.EF6.ssdl
==================================================================
--- System.Data.SQLite.Linq/Resources/SQLiteProviderServices.StoreSchemaDefinition.EF6.ssdl
+++ System.Data.SQLite.Linq/Resources/SQLiteProviderServices.StoreSchemaDefinition.EF6.ssdl
@@ -275,11 +275,11 @@
-
+
@@ -477,11 +477,11 @@
-
+
Index: System.Data.SQLite.Linq/Resources/SQLiteProviderServices.StoreSchemaDefinition.Linq.ssdl
==================================================================
--- System.Data.SQLite.Linq/Resources/SQLiteProviderServices.StoreSchemaDefinition.Linq.ssdl
+++ System.Data.SQLite.Linq/Resources/SQLiteProviderServices.StoreSchemaDefinition.Linq.ssdl
@@ -1,7 +1,7 @@
-
+
SELECT
'[' || TABLE_NAME || ']' COLLATE NOCASE [Id]
@@ -275,11 +275,11 @@
-
+
@@ -477,11 +477,11 @@
-
+
Index: System.Data.SQLite.Linq/SQL Generation/SqlBuilder.cs
==================================================================
--- System.Data.SQLite.Linq/SQL Generation/SqlBuilder.cs
+++ System.Data.SQLite.Linq/SQL Generation/SqlBuilder.cs
@@ -99,10 +99,14 @@
ISqlFragment sqlFragment = (o as ISqlFragment);
if (null != sqlFragment)
{
sqlFragment.WriteSql(writer, sqlGenerator);
}
+ else if (o is char)
+ {
+ writer.Write((char)o);
+ }
else
{
throw new InvalidOperationException();
}
}
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
@@ -118,11 +118,11 @@
/// with respect to the query. The names are derived from the original names,
/// with an integer as a suffix. e.g. CustomerId will be renamed to CustomerId1,
/// CustomerId2 etc.
///
/// Since the names generated are globally unique, they will not conflict when the
- /// columns of a JOIN SELECT statement are joined with another JOIN.
+ /// columns of a JOIN SELECT statement are joined with another JOIN.
///
///
///
///
/// Record flattening.
@@ -436,11 +436,11 @@
#endregion
#region Constructor
///
- /// Basic constructor.
+ /// Basic constructor.
///
private SqlGenerator(SQLiteProviderManifest manifest)
{
_manifest = manifest;
}
@@ -464,11 +464,11 @@
DbQueryCommandTree queryCommandTree = tree as DbQueryCommandTree;
if (queryCommandTree != null)
{
SqlGenerator sqlGen = new SqlGenerator(manifest);
parameters = null;
-
+
string sql = sqlGen.GenerateSql((DbQueryCommandTree)tree);
return sql;
}
@@ -873,13 +873,11 @@
case PrimitiveTypeKind.Int32:
result.Append(e.Value.ToString());
break;
case PrimitiveTypeKind.Binary:
- result.Append(" X'");
- result.Append(ByteArrayToBinaryString((Byte[])e.Value));
- result.Append("' ");
+ ToBlobLiteral((byte[])e.Value, result);
break;
case PrimitiveTypeKind.Boolean:
result.Append((bool)e.Value ? "1" : "0");
break;
@@ -887,11 +885,25 @@
case PrimitiveTypeKind.Byte:
result.Append(e.Value.ToString());
break;
case PrimitiveTypeKind.DateTime:
- result.Append(EscapeSingleQuote(SQLiteConvert.ToString((System.DateTime)e.Value, SQLiteDateFormats.ISO8601, DateTimeKind.Unspecified, null), false /* IsUnicode */));
+ bool needQuotes = NeedSingleQuotes(_manifest._dateTimeFormat);
+
+ string dateString = SQLiteConvert.ToString(
+ (System.DateTime)e.Value, _manifest._dateTimeFormat,
+ _manifest._dateTimeKind, _manifest._dateTimeFormatString);
+
+ if (needQuotes)
+ {
+ result.Append(EscapeSingleQuote(
+ dateString, false /* IsUnicode */));
+ }
+ else
+ {
+ result.Append(dateString);
+ }
break;
case PrimitiveTypeKind.Decimal:
string strDecimal = ((Decimal)e.Value).ToString(CultureInfo.InvariantCulture);
// if the decimal value has no decimal part, cast as decimal to preserve type
@@ -921,11 +933,18 @@
case PrimitiveTypeKind.Double:
result.Append(((Double)e.Value).ToString(CultureInfo.InvariantCulture));
break;
case PrimitiveTypeKind.Guid:
- result.Append(EscapeSingleQuote(e.Value.ToString(), false /* IsUnicode */));
+ {
+ object value = e.Value;
+
+ if (_manifest._binaryGuid && (value is Guid))
+ ToBlobLiteral(((Guid)value).ToByteArray(), result);
+ else
+ result.Append(EscapeSingleQuote(e.Value.ToString(), false /* IsUnicode */));
+ }
break;
case PrimitiveTypeKind.Int16:
result.Append(e.Value.ToString());
break;
@@ -1125,11 +1144,11 @@
///
/// - Canonical Functions - We recognize these by their dataspace, it is DataSpace.CSpace
/// - Store Functions - We recognize these by the BuiltInAttribute and not being Canonical
/// - User-defined Functions - All the rest except for Lambda functions
///
- /// We handle Canonical and Store functions the same way: If they are in the list of functions
+ /// We handle Canonical and Store functions the same way: If they are in the list of functions
/// that need special handling, we invoke the appropriate handler, otherwise we translate them to
/// FunctionName(arg1, arg2, ..., argn).
/// We translate user-defined functions to NamespaceName.FunctionName(arg1, arg2, ..., argn).
///
///
@@ -1176,43 +1195,43 @@
///
/// for general details.
/// We modify both the GroupBy and the Select fields of the SqlSelectStatement.
/// GroupBy gets just the keys without aliases,
/// and Select gets the keys and the aggregates with aliases.
- ///
+ ///
/// Whenever there exists at least one aggregate with an argument that is not is not a simple
- /// over ,
- /// we create a nested query in which we alias the arguments to the aggregates.
+ /// over ,
+ /// we create a nested query in which we alias the arguments to the aggregates.
/// That is due to the following two limitations of Sql Server:
///
- /// - If an expression being aggregated contains an outer reference, then that outer
+ ///
- If an expression being aggregated contains an outer reference, then that outer
/// reference must be the only column referenced in the expression
- /// - Sql Server cannot perform an aggregate function on an expression containing
+ ///
- Sql Server cannot perform an aggregate function on an expression containing
/// an aggregate or a subquery.
///
- ///
- /// The default translation, without inner query is:
- ///
- /// SELECT
- /// kexp1 AS key1, kexp2 AS key2,... kexpn AS keyn,
+ ///
+ /// The default translation, without inner query is:
+ ///
+ /// SELECT
+ /// kexp1 AS key1, kexp2 AS key2,... kexpn AS keyn,
/// aggf1(aexpr1) AS agg1, .. aggfn(aexprn) AS aggn
/// FROM input AS a
/// GROUP BY kexp1, kexp2, .. kexpn
- ///
+ ///
/// When we inject an innner query, the equivalent translation is:
- ///
- /// SELECT
- /// key1 AS key1, key2 AS key2, .. keyn AS keys,
+ ///
+ /// SELECT
+ /// key1 AS key1, key2 AS key2, .. keyn AS keys,
/// aggf1(agg1) AS agg1, aggfn(aggn) AS aggn
/// FROM (
- /// SELECT
- /// kexp1 AS key1, kexp2 AS key2,... kexpn AS keyn,
+ /// SELECT
+ /// kexp1 AS key1, kexp2 AS key2,... kexpn AS keyn,
/// aexpr1 AS agg1, .. aexprn AS aggn
/// FROM input AS a
/// ) as a
/// GROUP BY key1, key2, keyn
- ///
+ ///
///
///
/// A
public override ISqlFragment Visit(DbGroupByExpression e)
{
@@ -1238,11 +1257,11 @@
// The enumerator is shared by both the keys and the aggregates,
// so, we do not close it in between.
RowType groupByType = MetadataHelpers.GetEdmType(MetadataHelpers.GetEdmType(e.ResultType).TypeUsage);
- //Whenever there exists at least one aggregate with an argument that is not simply a PropertyExpression
+ //Whenever there exists at least one aggregate with an argument that is not simply a PropertyExpression
// over a VarRefExpression, we need a nested query in which we alias the arguments to the aggregates.
bool needsInnerQuery = NeedsInnerQuery(e.Aggregates);
SqlSelectStatement result;
if (needsInnerQuery)
@@ -1290,11 +1309,11 @@
innerQuery.Select.AppendLine();
innerQuery.Select.Append(keySql);
innerQuery.Select.Append(" AS ");
innerQuery.Select.Append(alias);
- //The outer resulting query projects over the key aliased in the inner query:
+ //The outer resulting query projects over the key aliased in the inner query:
// fromSymbol.Alias AS Alias
result.Select.Append(separator);
result.Select.AppendLine();
result.Select.Append(fromSymbol);
result.Select.Append(".");
@@ -1464,11 +1483,11 @@
SqlBuilder result = new SqlBuilder();
result.Append(e.Argument.Accept(this));
result.Append(" LIKE ");
result.Append(e.Pattern.Accept(this));
- // if the ESCAPE expression is a DbNullExpression, then that's tantamount to
+ // if the ESCAPE expression is a DbNullExpression, then that's tantamount to
// not having an ESCAPE at all
if (e.Escape.ExpressionKind != DbExpressionKind.Null)
{
result.Append(" ESCAPE ");
result.Append(e.Escape.Accept(this));
@@ -1814,14 +1833,14 @@
///
/// For Sql9 it translates to:
/// SELECT Y.x1, Y.x2, ..., Y.xn
/// FROM (
- /// SELECT X.x1, X.x2, ..., X.xn, row_number() OVER (ORDER BY sk1, sk2, ...) AS [row_number]
- /// FROM input as X
+ /// SELECT X.x1, X.x2, ..., X.xn, row_number() OVER (ORDER BY sk1, sk2, ...) AS [row_number]
+ /// FROM input as X
/// ) as Y
- /// WHERE Y.[row_number] > count
+ /// WHERE Y.[row_number] > count
/// ORDER BY sk1, sk2, ...
///
///
/// A
public override ISqlFragment Visit(DbSkipExpression e)
@@ -2617,12 +2636,12 @@
return handlers[e.Function.Name](this, e);
}
///
/// Handles functions that are translated into TSQL operators.
- /// The given function should have one or two arguments.
- /// Functions with one arguemnt are translated into
+ /// The given function should have one or two arguments.
+ /// Functions with one arguemnt are translated into
/// op arg
/// Functions with two arguments are translated into
/// arg0 op arg1
/// Also, the arguments can be optionaly enclosed in parethesis
///
@@ -2689,11 +2708,11 @@
private static ISqlFragment HandleGetDateFunction(SqlGenerator sqlgen, DbFunctionExpression e)
{
SqlBuilder result = new SqlBuilder();
Debug.Assert(e.Arguments.Count == 0, "Canonical getdate function should have no arguments");
- switch (sqlgen._manifest._dateFormat)
+ switch (sqlgen._manifest._dateTimeFormat)
{
case SQLiteDateFormats.Ticks:
result.Append("(STRFTIME('%s', 'now') * 10000000 + 621355968000000000)");
break;
case SQLiteDateFormats.JulianDay:
@@ -2710,11 +2729,11 @@
private static ISqlFragment HandleGetUtcDateFunction(SqlGenerator sqlgen, DbFunctionExpression e)
{
SqlBuilder result = new SqlBuilder();
Debug.Assert(e.Arguments.Count == 0, "Canonical getutcdate function should have no arguments");
- switch (sqlgen._manifest._dateFormat)
+ switch (sqlgen._manifest._dateTimeFormat)
{
case SQLiteDateFormats.Ticks:
result.Append("(STRFTIME('%s', 'now', 'utc') * 10000000 + 621355968000000000)");
break;
case SQLiteDateFormats.JulianDay:
@@ -2769,11 +2788,11 @@
// expand the datepart literal as tsql kword
result.Append(trans);
result.Append("', ");
- switch (sqlgen._manifest._dateFormat)
+ switch (sqlgen._manifest._dateTimeFormat)
{
case SQLiteDateFormats.Ticks:
result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[1].Accept(sqlgen)));
break;
default:
@@ -2785,11 +2804,11 @@
}
else
{
result.Append("CAST(SUBSTR(STRFTIME('%f', ");
- switch (sqlgen._manifest._dateFormat)
+ switch (sqlgen._manifest._dateTimeFormat)
{
case SQLiteDateFormats.Ticks:
result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[1].Accept(sqlgen)));
break;
default:
@@ -2812,11 +2831,11 @@
private static ISqlFragment HandleCanonicalFunctionDateAdd(SqlGenerator sqlgen, DbFunctionExpression e)
{
SqlBuilder result = new SqlBuilder();
Debug.Assert(e.Arguments.Count == 2, "Canonical datepart functions should have exactly two arguments");
- switch (sqlgen._manifest._dateFormat)
+ switch (sqlgen._manifest._dateTimeFormat)
{
case SQLiteDateFormats.Ticks:
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:
@@ -2829,21 +2848,21 @@
return result;
}
///
- /// DateSubtract(datetime1, datetime2) -> DATEDIFF ( seconds , startdate , enddate )
+ /// DateSubtract(datetime1, datetime2) -> DATEDIFF ( seconds , startdate , enddate )
///
///
///
///
private static ISqlFragment HandleCanonicalFunctionDateSubtract(SqlGenerator sqlgen, DbFunctionExpression e)
{
SqlBuilder result = new SqlBuilder();
Debug.Assert(e.Arguments.Count == 2, "Canonical datepart functions should have exactly two arguments");
- switch (sqlgen._manifest._dateFormat)
+ switch (sqlgen._manifest._dateTimeFormat)
{
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;
default:
@@ -2853,11 +2872,11 @@
return result;
}
///
- /// Handler for canonical functions for extracting date parts.
+ /// Handler for canonical functions for extracting date parts.
/// For example:
/// Year(date) -> DATEPART( year, date)
///
///
///
@@ -2875,11 +2894,11 @@
result.Append(trans);
result.Append("', ");
Debug.Assert(e.Arguments.Count == 1, "Canonical datepart functions should have exactly one argument");
- switch (sqlgen._manifest._dateFormat)
+ switch (sqlgen._manifest._dateTimeFormat)
{
case SQLiteDateFormats.Ticks:
result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[0].Accept(sqlgen)));
break;
default:
@@ -3312,11 +3331,11 @@
}
}
///
/// Translates a list of SortClauses.
- /// Used in the translation of OrderBy
+ /// Used in the translation of OrderBy
///
/// The SqlBuilder to which the sort keys should be appended
///
void AddSortKeys(SqlBuilder orderByClause, IList sortKeys)
{
@@ -3423,10 +3442,29 @@
return selectStatement;
}
+ ///
+ /// Determines if values of the specified
+ /// require wrapping in single quotes.
+ ///
+ ///
+ /// The format.
+ ///
+ ///
+ /// Non-zero if single quotes are required for a value in the specified
+ /// .
+ ///
+ private static bool NeedSingleQuotes(
+ SQLiteDateFormats format
+ )
+ {
+ return format != SQLiteDateFormats.Ticks &&
+ format != SQLiteDateFormats.JulianDay &&
+ format != SQLiteDateFormats.UnixEpoch;
+ }
///
/// Before we embed a string literal in a SQL string, we should
/// convert all ' to '', and enclose the whole string in single quotes.
///
@@ -3437,12 +3475,12 @@
{
return "'" + s.Replace("'", "''") + "'";
}
///
- /// Returns the sql primitive/native type name.
- /// It will include size, precision or scale depending on type information present in the
+ /// Returns the sql primitive/native type name.
+ /// It will include size, precision or scale depending on type information present in the
/// type facets
///
///
///
private string GetSqlPrimitiveType(TypeUsage type)
@@ -3565,11 +3603,11 @@
{
ISqlFragment result;
if (e.ExpressionKind == DbExpressionKind.Constant)
{
- //For constant expression we should not cast the value,
+ //For constant expression we should not cast the value,
// thus we don't go throught the default DbConstantExpression handling
SqlBuilder sqlBuilder = new SqlBuilder();
sqlBuilder.Append(((DbConstantExpression)e).Value.ToString());
result = sqlBuilder;
}
@@ -3650,11 +3688,11 @@
{
switch (expressionKind)
{
case DbExpressionKind.Distinct:
return result.Top == null
- // The projection after distinct may not project all
+ // The projection after distinct may not project all
// columns used in the Order By
&& result.OrderBy.IsEmpty;
case DbExpressionKind.Filter:
return result.Select.IsEmpty
@@ -3773,11 +3811,11 @@
/// -- originally {expression}
/// -- change that to
/// SELECT *
/// FROM {expression} as c
///
- ///
+ ///
/// DbLimitExpression needs to start the statement but not add the default columns
///
///
///
///
@@ -3959,24 +3997,50 @@
//result.Append(".");
result.Append(QuoteIdentifier(storeFunctionName));
}
}
- static string ByteArrayToBinaryString(Byte[] binaryArray)
- {
- StringBuilder sb = new StringBuilder(binaryArray.Length * 2);
- for (int i = 0; i < binaryArray.Length; i++)
- {
- sb.Append(hexDigits[(binaryArray[i] & 0xF0) >> 4]).Append(hexDigits[binaryArray[i] & 0x0F]);
- }
- return sb.ToString();
+ ///
+ /// Appends the literal BLOB string representation of the specified
+ /// byte array to the .
+ ///
+ ///
+ /// The byte array to be formatted as a literal BLOB string.
+ ///
+ ///
+ /// The object to use. If null, an exception
+ /// will be thrown.
+ ///
+ private static void ToBlobLiteral(
+ byte[] bytes,
+ SqlBuilder builder
+ )
+ {
+ if (builder == null)
+ throw new ArgumentNullException("builder");
+
+ if (bytes == null)
+ {
+ builder.Append("NULL"); /* TODO: Reasonable? */
+ return;
+ }
+
+ builder.Append(" X'");
+
+ for (int index = 0; index < bytes.Length; index++)
+ {
+ builder.Append(hexDigits[(bytes[index] & 0xF0) >> 4]);
+ builder.Append(hexDigits[bytes[index] & 0x0F]);
+ }
+
+ builder.Append("' ");
}
///
/// Helper method for the Group By visitor
/// Returns true if at least one of the aggregates in the given list
- /// has an argument that is not a
+ /// has an argument that is not a
/// over
///
///
///
static bool NeedsInnerQuery(IList aggregates)
@@ -3991,11 +4055,11 @@
}
return false;
}
///
- /// Determines whether the given expression is a
+ /// Determines whether the given expression is a
/// over
///
///
///
static bool IsPropertyOverVarRef(DbExpression expression)
@@ -4012,11 +4076,11 @@
}
return true;
}
#endregion
-
+
private class KeyFieldExpressionComparer : IEqualityComparer
{
// Fields
internal static readonly SqlGenerator.KeyFieldExpressionComparer Singleton = new SqlGenerator.KeyFieldExpressionComparer();
Index: System.Data.SQLite.Linq/SQLiteProviderManifest.cs
==================================================================
--- System.Data.SQLite.Linq/SQLiteProviderManifest.cs
+++ System.Data.SQLite.Linq/SQLiteProviderManifest.cs
@@ -10,49 +10,204 @@
#else
namespace System.Data.SQLite.Linq
#endif
{
using System;
- using System.Data;
- using System.Reflection;
+ using System.Collections.Generic;
using System.IO;
+ using System.Reflection;
+
+#if !PLATFORM_COMPACTFRAMEWORK
+ using System.Text;
+#endif
+
using System.Xml;
- using System.Data.Common;
#if USE_ENTITY_FRAMEWORK_6
using System.Data.Entity.Core;
using System.Data.Entity.Core.Common;
using System.Data.Entity.Core.Metadata.Edm;
#else
+ using System.Data.Common;
using System.Data.Metadata.Edm;
#endif
///
/// The Provider Manifest for SQL Server
///
internal sealed class SQLiteProviderManifest : DbXmlEnabledProviderManifest
{
- internal SQLiteDateFormats _dateFormat;
+ internal SQLiteDateFormats _dateTimeFormat;
+ internal DateTimeKind _dateTimeKind;
+ internal string _dateTimeFormatString;
+ internal bool _binaryGuid;
///
/// Constructs the provider manifest.
///
///
- /// We pass the token as a DateTimeFormat enum text, because all the datetime functions
- /// are vastly different depending on how the user is opening the connection
+ /// Previously, the manifest token was interpreted as a ,
+ /// because the functions are vastly different depending on the
+ /// connection was opened. However, the manifest token may specify a connection string
+ /// instead. WARNING: Only the "DateTimeFormat", "DateTimeKind", "DateTimeFormatString",
+ /// and "BinaryGUID" connection parameters are extracted from it. All other connection
+ /// parameters, if any are present, are silently ignored.
///
- /// A token used to infer the capabilities of the store
+ ///
+ /// A token used to infer the capabilities of the store.
+ ///
public SQLiteProviderManifest(string manifestToken)
- : base(SQLiteProviderManifest.GetProviderManifest())
+ : base(GetProviderManifest())
{
- _dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats), manifestToken, true);
+ SetFromOptions(ParseProviderManifestToken(GetProviderManifestToken(manifestToken)));
}
- internal static XmlReader GetProviderManifest()
+ private static XmlReader GetProviderManifest()
{
return GetXmlResource("System.Data.SQLite.SQLiteProviderServices.ProviderManifest.xml");
}
+
+ ///
+ /// Determines and returns the effective provider manifest token to use,
+ /// based on the specified provider manifest token and the environment,
+ /// if applicable.
+ ///
+ ///
+ /// The original provider manifest token passed to the constructor for this
+ /// class.
+ ///
+ ///
+ /// The effective provider manifest token.
+ ///
+ private static string GetProviderManifestToken(
+ string manifestToken
+ )
+ {
+#if !PLATFORM_COMPACTFRAMEWORK
+ string value = UnsafeNativeMethods.GetSettingValue(
+ "AppendManifestToken_SQLiteProviderManifest", null);
+
+ if (String.IsNullOrEmpty(value))
+ return manifestToken;
+
+ int capacity = value.Length;
+
+ if (manifestToken != null)
+ capacity += manifestToken.Length;
+
+ StringBuilder builder = new StringBuilder(capacity);
+
+ builder.Append(manifestToken);
+ builder.Append(value);
+
+ return builder.ToString();
+#else
+ //
+ // NOTE: The .NET Compact Framework lacks environment variable support.
+ // Therefore, just return the original provider manifest token
+ // verbatim in this case.
+ //
+ return manifestToken;
+#endif
+ }
+
+ ///
+ /// Attempts to parse a provider manifest token. It must contain either a
+ /// legacy string that specifies the value
+ /// -OR- string that uses the standard connection string syntax; otherwise,
+ /// the results are undefined.
+ ///
+ ///
+ /// The manifest token to parse.
+ ///
+ ///
+ /// The dictionary containing the connection string parameters.
+ ///
+ private static SortedList ParseProviderManifestToken(
+ string manifestToken
+ )
+ {
+ return SQLiteConnection.ParseConnectionString(manifestToken, false, true);
+ }
+
+ ///
+ /// Attempts to set the provider manifest options from the specified
+ /// connection string parameters. An exception may be thrown if one
+ /// or more of the connection string parameter values do not conform
+ /// to the expected type.
+ ///
+ ///
+ /// The dictionary containing the connection string parameters.
+ ///
+ internal void SetFromOptions(
+ SortedList opts
+ )
+ {
+ _dateTimeFormat = SQLiteConnection.DefaultDateTimeFormat;
+ _dateTimeKind = SQLiteConnection.DefaultDateTimeKind;
+ _dateTimeFormatString = SQLiteConnection.DefaultDateTimeFormatString;
+ _binaryGuid = /* SQLiteConnection.DefaultBinaryGUID; */ false; /* COMPAT: Legacy. */
+
+ if (opts == null)
+ return;
+
+#if !PLATFORM_COMPACTFRAMEWORK
+ string[] names = Enum.GetNames(typeof(SQLiteDateFormats));
+#else
+ string[] names = {
+ SQLiteDateFormats.Ticks.ToString(),
+ SQLiteDateFormats.ISO8601.ToString(),
+ SQLiteDateFormats.JulianDay.ToString(),
+ SQLiteDateFormats.UnixEpoch.ToString(),
+ SQLiteDateFormats.InvariantCulture.ToString(),
+ SQLiteDateFormats.CurrentCulture.ToString(),
+ "Default"
+ };
+#endif
+
+ foreach (string name in names)
+ {
+ if (String.IsNullOrEmpty(name))
+ continue;
+
+ object value = SQLiteConnection.FindKey(opts, name, null);
+
+ if (value == null)
+ continue;
+
+ _dateTimeFormat = (SQLiteDateFormats)Enum.Parse(
+ typeof(SQLiteDateFormats), name, true);
+ }
+
+ object enumValue;
+
+ enumValue = SQLiteConnection.TryParseEnum(
+ typeof(SQLiteDateFormats), SQLiteConnection.FindKey(
+ opts, "DateTimeFormat", null), true);
+
+ if (enumValue is SQLiteDateFormats)
+ _dateTimeFormat = (SQLiteDateFormats)enumValue;
+
+ enumValue = SQLiteConnection.TryParseEnum(
+ typeof(DateTimeKind), SQLiteConnection.FindKey(
+ opts, "DateTimeKind", null), true);
+
+ if (enumValue is DateTimeKind)
+ _dateTimeKind = (DateTimeKind)enumValue;
+
+ string stringValue = SQLiteConnection.FindKey(
+ opts, "DateTimeFormatString", null);
+
+ if (stringValue != null)
+ _dateTimeFormatString = stringValue;
+
+ stringValue = SQLiteConnection.FindKey(
+ opts, "BinaryGUID", null);
+
+ if (stringValue != null)
+ _binaryGuid = SQLiteConvert.ToBoolean(stringValue);
+ }
///
/// Returns manifest information for the provider
///
/// The name of the information to be retrieved.
Index: System.Data.SQLite.Linq/SQLiteProviderServices.cs
==================================================================
--- System.Data.SQLite.Linq/SQLiteProviderServices.cs
+++ System.Data.SQLite.Linq/SQLiteProviderServices.cs
@@ -9,16 +9,16 @@
namespace System.Data.SQLite.EF6
#else
namespace System.Data.SQLite.Linq
#endif
{
- using System;
- using System.Data.Common;
- using System.Diagnostics;
+ using System;
using System.Collections.Generic;
- using System.Text;
+ using System.Data.Common;
+ using System.Diagnostics;
using System.Globalization;
+ using System.Text;
#if USE_ENTITY_FRAMEWORK_6
using System.Data.Entity.Core.Common;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Core.Common.CommandTrees;
@@ -107,24 +107,18 @@
throw;
}
}
protected override string GetDbProviderManifestToken(DbConnection connection)
- {
- if (String.IsNullOrEmpty(connection.ConnectionString))
- throw new ArgumentNullException("ConnectionString");
-
- bool parseViaFramework = false;
-
- if (connection is SQLiteConnection)
- parseViaFramework = ((SQLiteConnection)connection).ParseViaFramework;
-
- SortedList opts = parseViaFramework ?
- SQLiteConnection.ParseConnectionStringViaFramework(connection.ConnectionString, false) :
- SQLiteConnection.ParseConnectionString(connection.ConnectionString);
-
- return SQLiteConnection.FindKey(opts, "DateTimeFormat", "ISO8601");
+ {
+ if (connection == null)
+ throw new ArgumentNullException("connection");
+
+ if (String.IsNullOrEmpty(connection.ConnectionString))
+ throw new ArgumentNullException("ConnectionString");
+
+ return connection.ConnectionString;
}
protected override DbProviderManifest GetDbProviderManifest(string versionHint)
{
return new SQLiteProviderManifest(versionHint);
Index: System.Data.SQLite/Configurations/System.Data.SQLite.dll.config
==================================================================
--- System.Data.SQLite/Configurations/System.Data.SQLite.dll.config
+++ System.Data.SQLite/Configurations/System.Data.SQLite.dll.config
@@ -7,10 +7,24 @@
* Released to the public domain, use at your own risk!
*
-->
+
+
+
+
+
+
|