/// <summary> /// Given metadata name-value IDs, return name-value string->object values /// </summary> /// <param name="ctxt">Database connection</param> /// <param name="ids">name=>value IDs</param> /// <returns></returns> public static async Task <Dictionary <string, object> > GetMetadataValuesAsync(Context ctxt, Dictionary <int, long> ids) { var totalTimer = ScopeTiming.StartTiming(); try { var retVal = new Dictionary <string, object>(ids.Count); if (ids.Count == 0) { return(retVal); } await Names.CacheNamesAsync(ctxt, ids.Keys).ConfigureAwait(false); await Values.CacheValuesAsync(ctxt, ids.Values).ConfigureAwait(false); foreach (var kvp in ids) { NameObj name = await Names.GetNameAsync(ctxt, kvp.Key).ConfigureAwait(false); object value = await Values.GetValueAsync(ctxt, kvp.Value).ConfigureAwait(false); retVal.Add(name.name, value); } return(retVal); } finally { ScopeTiming.RecordScope("NameValues.GetMetadataValuesAsync", totalTimer); } }
public void TestNames() { using (var ctxt = TestUtils.GetCtxt()) { int tableId = Tables.GetIdAsync(ctxt, "sometable").Result; int firstId = Names.GetIdAsync(ctxt, tableId, "foobar").Result; int secondId = Names.GetIdAsync(ctxt, tableId, "foobar").Result; Assert.AreEqual(firstId, secondId); NameObj name = Names.GetNameAsync(ctxt, secondId).Result; Assert.AreEqual("foobar", name.name); Assert.IsTrue(!name.isNumeric); Assert.AreEqual("foobar", Names.GetNameAsync(ctxt, secondId).Result.name); Assert.AreEqual(name.isNumeric, Names.GetNameIsNumericAsync(ctxt, firstId).Result); int thirdId = Names.GetIdAsync(ctxt, tableId, "bletmonkey", isNumeric: true).Result; int fourthId = Names.GetIdAsync(ctxt, tableId, "bletmonkey").Result; Assert.AreEqual(thirdId, fourthId); Assert.AreNotEqual(firstId, thirdId); NameObj name2 = Names.GetNameAsync(ctxt, fourthId).Result; Assert.AreEqual("bletmonkey", name2.name); Assert.IsTrue(name2.isNumeric); Assert.AreEqual("bletmonkey", Names.GetNameAsync(ctxt, fourthId).Result.name); Assert.AreEqual(name2.isNumeric, Names.GetNameIsNumericAsync(ctxt, fourthId).Result); } }
/// <summary> /// Given a name ID, get info about the name /// </summary> /// <param name="ctxt">Database connection</param> /// <param name="id">Name database row ID</param> /// <returns>Info about the name</returns> public static async Task <NameObj> GetNameAsync(Context ctxt, int id) { if (id < 0) { return(null); } NameObj obj; if (sm_cacheBack.TryGetValue(id, out obj)) { return(obj); } string sql = $"SELECT tableid, name, isNumeric FROM names WHERE id = {id}"; using (var reader = await ctxt.Db.ExecuteReaderAsync(sql).ConfigureAwait(false)) { if (!await reader.ReadAsync().ConfigureAwait(false)) { throw new MetaStringsException($"Names.GetName fails to find record: {id}"); } obj = new NameObj() { id = id, tableId = reader.GetInt32(0), name = reader.GetString(1), isNumeric = reader.GetBoolean(2) }; sm_cacheBack[id] = obj; return(obj); } }
/// <summary> /// Seed the cache with info for a set of name IDs /// </summary> /// <param name="ctxt">Database connection</param> /// <param name="ids">Name IDs to cache the info of</param> public static async Task CacheNamesAsync(Context ctxt, IEnumerable <int> ids) { var totalTimer = ScopeTiming.StartTiming(); try { var stillToGet = ids.Where(id => !sm_cacheBack.ContainsKey(id)); if (!stillToGet.Any()) { return; } var nameIdInPart = string.Join(",", stillToGet.Select(i => i.ToString())); var sql = $"SELECT id, tableid, name, isNumeric FROM names WHERE id IN ({nameIdInPart})"; if (sql.Length > 1000 * 1000) { throw new MetaStringsException("GetNames query exceeds SQL batch limit of 1M. Use smaller batches of items."); } using (var reader = await ctxt.Db.ExecuteReaderAsync(sql).ConfigureAwait(false)) { while (await reader.ReadAsync().ConfigureAwait(false)) { int id = reader.GetInt32(0); sm_cacheBack[id] = new NameObj() { id = id, tableId = reader.GetInt32(1), name = reader.GetString(2), isNumeric = reader.GetBoolean(3) }; } } } finally { ScopeTiming.RecordScope("Names.CacheNames", totalTimer); } }