diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs b/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs index c6e2bace6f7..20e54f3980d 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -17,6 +18,8 @@ internal class SqliteDataRecord : SqliteValueReader, IDisposable private readonly SqliteConnection _connection; private byte[][]? _blobCache; private int?[]? _typeCache; + private Dictionary? _columnNameOrdinalCache; + private string[]? _columnNameCache; private bool _stepped; private int? _rowidOrdinal; @@ -100,7 +103,7 @@ protected override T GetNull(int ordinal) public virtual string GetName(int ordinal) { - var name = sqlite3_column_name(Handle, ordinal).utf8_to_string(); + var name = _columnNameCache?[ordinal] ?? sqlite3_column_name(Handle, ordinal).utf8_to_string(); if (name == null && (ordinal < 0 || ordinal >= FieldCount)) { @@ -108,18 +111,27 @@ public virtual string GetName(int ordinal) throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null); } + _columnNameCache ??= new string[FieldCount]; + _columnNameCache[ordinal] = name!; + return name!; } public virtual int GetOrdinal(string name) { - for (var i = 0; i < FieldCount; i++) + if (_columnNameOrdinalCache == null) { - if (GetName(i) == name) + _columnNameOrdinalCache = new Dictionary(); + for (var i = 0; i < FieldCount; i++) { - return i; + _columnNameOrdinalCache[GetName(i)] = i; } } + + if (_columnNameOrdinalCache.TryGetValue(name, out var ordinal)) + { + return ordinal; + } // NB: Message is provided by framework throw new ArgumentOutOfRangeException(nameof(name), name, message: null); diff --git a/test/Microsoft.Data.Sqlite.Tests/SqliteDataReaderTest.cs b/test/Microsoft.Data.Sqlite.Tests/SqliteDataReaderTest.cs index 76582ab94e5..59534c302b4 100644 --- a/test/Microsoft.Data.Sqlite.Tests/SqliteDataReaderTest.cs +++ b/test/Microsoft.Data.Sqlite.Tests/SqliteDataReaderTest.cs @@ -1227,6 +1227,9 @@ public void GetName_works() using (var reader = connection.ExecuteReader("SELECT 1 AS Id;")) { Assert.Equal("Id", reader.GetName(0)); + + // NB: Repeated to use caching + Assert.Equal("Id", reader.GetName(0)); } } } @@ -1266,6 +1269,9 @@ public void GetOrdinal_works() using (var reader = connection.ExecuteReader("SELECT 1 AS Id;")) { Assert.Equal(0, reader.GetOrdinal("Id")); + + // NB: Repeated to use caching + Assert.Equal(0, reader.GetOrdinal("Id")); } } }