diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteCommand.cs b/src/Microsoft.Data.Sqlite.Core/SqliteCommand.cs index f8a6e3b99ee..a6d00112b0d 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteCommand.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteCommand.cs @@ -24,8 +24,7 @@ namespace Microsoft.Data.Sqlite /// Async Limitations public class SqliteCommand : DbCommand { - private readonly Lazy _parameters = new Lazy( - () => new SqliteParameterCollection()); + private SqliteParameterCollection _parameters; private readonly List _preparedStatements = new List(); private SqliteConnection _connection; @@ -165,7 +164,7 @@ protected override DbTransaction DbTransaction /// The collection of parameters used by the command. /// Parameters public new virtual SqliteParameterCollection Parameters - => _parameters.Value; + => _parameters ??= new SqliteParameterCollection(); /// /// Gets the collection of parameters used by the command. @@ -326,12 +325,7 @@ private IEnumerable GetStatements(Stopwatch timer) ? PrepareAndEnumerateStatements(timer) : _preparedStatements) { - var boundParams = 0; - - if (_parameters.IsValueCreated) - { - boundParams = _parameters.Value.Bind(stmt); - } + var boundParams = _parameters?.Bind(stmt) ?? 0; var expectedParams = sqlite3_bind_parameter_count(stmt); if (expectedParams != boundParams) @@ -341,8 +335,8 @@ private IEnumerable GetStatements(Stopwatch timer) { var name = sqlite3_bind_parameter_name(stmt, i).utf8_to_string(); - if (_parameters.IsValueCreated - && !_parameters.Value.Cast().Any(p => p.ParameterName == name)) + if (_parameters != null + && !_parameters.Cast().Any(p => p.ParameterName == name)) { unboundParams.Add(name); } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs index 05092a51f41..d3e8ec0d28d 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs @@ -27,18 +27,14 @@ public partial class SqliteConnection : DbConnection private readonly List> _commands = new List>(); - private readonly Dictionary _collations - = new Dictionary(StringComparer.OrdinalIgnoreCase); + private Dictionary _collations; - private readonly Dictionary<(string name, int arity), (int flags, object state, delegate_function_scalar func)> _functions - = new Dictionary<(string, int), (int, object, delegate_function_scalar)>(FunctionsKeyComparer.Instance); + private Dictionary<(string name, int arity), (int flags, object state, delegate_function_scalar func)> _functions; - private readonly Dictionary<(string name, int arity), (int flags, object state, delegate_function_aggregate_step func_step, - delegate_function_aggregate_final func_final)> _aggregates - = new Dictionary<(string, int), (int, object, delegate_function_aggregate_step, delegate_function_aggregate_final)>( - FunctionsKeyComparer.Instance); + private Dictionary<(string name, int arity), (int flags, object state, delegate_function_aggregate_step func_step, + delegate_function_aggregate_final func_final)> _aggregates; - private readonly HashSet<(string file, string proc)> _extensions = new HashSet<(string, string)>(); + private HashSet<(string file, string proc)> _extensions; private string _connectionString; private ConnectionState _state; @@ -276,27 +272,37 @@ public override void Open() this.ExecuteNonQuery("PRAGMA recursive_triggers = 1;"); } - foreach (var item in _collations) + if (_collations != null) { - rc = sqlite3_create_collation(_db, item.Key, item.Value.state, item.Value.collation); - SqliteException.ThrowExceptionForRC(rc, _db); + foreach (var item in _collations) + { + rc = sqlite3_create_collation(_db, item.Key, item.Value.state, item.Value.collation); + SqliteException.ThrowExceptionForRC(rc, _db); + } } - foreach (var item in _functions) + if (_functions != null) { - rc = sqlite3_create_function(_db, item.Key.name, item.Key.arity, item.Value.state, item.Value.func); - SqliteException.ThrowExceptionForRC(rc, _db); + foreach (var item in _functions) + { + rc = sqlite3_create_function(_db, item.Key.name, item.Key.arity, item.Value.state, item.Value.func); + SqliteException.ThrowExceptionForRC(rc, _db); + } } - foreach (var item in _aggregates) + if (_aggregates != null) { - rc = sqlite3_create_function( - _db, item.Key.name, item.Key.arity, item.Value.state, item.Value.func_step, item.Value.func_final); - SqliteException.ThrowExceptionForRC(rc, _db); + foreach (var item in _aggregates) + { + rc = sqlite3_create_function( + _db, item.Key.name, item.Key.arity, item.Value.state, item.Value.func_step, item.Value.func_final); + SqliteException.ThrowExceptionForRC(rc, _db); + } } var extensionsEnabledForLoad = false; - if (_extensions.Count != 0) + if (_extensions != null + && _extensions.Count != 0) { rc = sqlite3_enable_load_extension(_db, 1); SqliteException.ThrowExceptionForRC(rc, _db); @@ -449,6 +455,7 @@ public virtual void CreateCollation(string name, T state, Func(StringComparer.OrdinalIgnoreCase); _collations[name] = (state, collation); } @@ -546,6 +553,7 @@ public virtual void LoadExtension(string file, string proc = null) } } + _extensions ??= new HashSet<(string, string)>(); _extensions.Add((file, proc)); } @@ -677,6 +685,7 @@ private void CreateFunctionCore( SqliteException.ThrowExceptionForRC(rc, _db); } + _functions ??= new Dictionary<(string, int), (int, object, delegate_function_scalar)>(FunctionsKeyComparer.Instance); _functions[(name, arity)] = (flags, state, func); } @@ -771,6 +780,8 @@ private void CreateAggregateCore( SqliteException.ThrowExceptionForRC(rc, _db); } + _aggregates ??= new Dictionary<(string, int), (int, object, delegate_function_aggregate_step, delegate_function_aggregate_final)>( + FunctionsKeyComparer.Instance); _aggregates[(name, arity)] = (flags, state, func_step, func_final); } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs b/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs index a1f4cae9902..1ac1c8725a7 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs @@ -15,8 +15,8 @@ namespace Microsoft.Data.Sqlite internal class SqliteDataRecord : SqliteValueReader, IDisposable { private readonly SqliteConnection _connection; - private readonly byte[][] _blobCache; - private readonly int?[] _typeCache; + private byte[][] _blobCache; + private int?[] _typeCache; private bool _stepped; private int? _rowidOrdinal; @@ -25,8 +25,6 @@ public SqliteDataRecord(sqlite3_stmt stmt, bool hasRows, SqliteConnection connec Handle = stmt; HasRows = hasRows; _connection = connection; - _blobCache = new byte[FieldCount][]; - _typeCache = new int?[FieldCount]; } public virtual object this[string name] @@ -146,10 +144,11 @@ public virtual Type GetFieldType(int ordinal) var sqliteType = GetSqliteType(ordinal); if (sqliteType == SQLITE_NULL) { - sqliteType = _typeCache[ordinal] ?? Sqlite3AffinityType(GetDataTypeName(ordinal)); + sqliteType = _typeCache?[ordinal] ?? Sqlite3AffinityType(GetDataTypeName(ordinal)); } else { + _typeCache ??= new int?[FieldCount]; _typeCache[ordinal] = sqliteType; } @@ -317,7 +316,10 @@ public bool Read() var rc = sqlite3_step(Handle); SqliteException.ThrowExceptionForRC(rc, _connection.Handle); - Array.Clear(_blobCache, 0, _blobCache.Length); + if (_blobCache != null) + { + Array.Clear(_blobCache, 0, _blobCache.Length); + } return rc != SQLITE_DONE; } @@ -334,10 +336,11 @@ private byte[] GetCachedBlob(int ordinal) throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null); } - var blob = _blobCache[ordinal]; + var blob = _blobCache?[ordinal]; if (blob == null) { blob = GetBlob(ordinal); + _blobCache ??= new byte[FieldCount][]; _blobCache[ordinal] = blob; }