using Connected.Entities.Annotations; using Connected.Entities.Storage; using System.Collections.Concurrent; using System.Reflection; namespace Connected.Data.Update; internal sealed class UpdateCommandBuilder : CommandBuilder { private static readonly ConcurrentDictionary _cache; static UpdateCommandBuilder() { _cache = new(); } private static ConcurrentDictionary Cache => _cache; private bool SupportsConcurrency { get; set; } protected override bool TryGetExisting(out StorageOperation? result) { return Cache.TryGetValue(Entity.GetType().FullName, out result); } protected override StorageOperation OnBuild() { WriteLine($"UPDATE [{Schema.Schema}].[{Schema.Name}] SET"); WriteAssignments(); WriteWhere(); Trim(); Write(';'); var result = new StorageOperation { CommandText = CommandText, Concurrency = SupportsConcurrency ? DataConcurrencyMode.Enabled : DataConcurrencyMode.Disabled }; foreach (var parameter in Parameters) result.AddParameter(parameter); Cache.TryAdd(Entity.GetType().FullName, result); return result; } private void WriteAssignments() { foreach (var property in Properties) { if (property.GetCustomAttribute() is not null || IsVersion(property)) { if (IsVersion(property)) SupportsConcurrency = true; WhereProperties.Add(property); continue; } var parameter = CreateParameter(property); WriteLine($"{ColumnName(property)} = {parameter.Name},"); } Trim(); } private void WriteWhere() { WriteLine(string.Empty); for (var i = 0; i < WhereProperties.Count; i++) { var property = WhereProperties[i]; var parameter = CreateParameter(property); if (i == 0) WriteLine($" WHERE {ColumnName(property)} = {parameter.Name}"); else WriteLine($" AND {ColumnName(property)} = {parameter.Name}"); } } }