forked from ddrilling/AsbCloudServer
refactor built query with less mem allocation.
This commit is contained in:
parent
db0b430d93
commit
361aceed96
@ -13,7 +13,7 @@ namespace AsbCloudDb
|
||||
{
|
||||
static Dictionary<Type, IQueryStringFactory> QueryFactories { get; set; } = new Dictionary<Type, IQueryStringFactory>();
|
||||
|
||||
static IQueryStringFactory GetQueryStringFactory<T>(DbSet<T> dbset)
|
||||
static QueryStringFactory<T> GetQueryStringFactory<T>(DbSet<T> dbset)
|
||||
where T : class
|
||||
{
|
||||
var t = typeof(T);
|
||||
@ -30,8 +30,9 @@ namespace AsbCloudDb
|
||||
public static Task<int> ExecInsertOrUpdateAsync<T>(this Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade database, DbSet<T> dbset, IEnumerable<T> items, CancellationToken token)
|
||||
where T : class
|
||||
{
|
||||
var factory = (QueryStringFactory<T>)GetQueryStringFactory(dbset);
|
||||
var factory = GetQueryStringFactory(dbset);
|
||||
var query = factory.MakeInsertOrUpdateSql(items);
|
||||
|
||||
return database.ExecuteSqlRawAsync(query, token);
|
||||
}
|
||||
}
|
||||
@ -41,10 +42,11 @@ namespace AsbCloudDb
|
||||
class QueryStringFactory<T> : IQueryStringFactory
|
||||
where T : class
|
||||
{
|
||||
private readonly string insertHeader;
|
||||
|
||||
private readonly string pk;
|
||||
private readonly string tableName;
|
||||
private readonly string colunmsString;
|
||||
private readonly string conflictUpdateSet;
|
||||
private readonly string conflictBody;
|
||||
private readonly IEnumerable<IClrPropertyGetter> getters;
|
||||
|
||||
public QueryStringFactory(DbSet<T> dbset)
|
||||
@ -56,8 +58,11 @@ namespace AsbCloudDb
|
||||
tableName = dbset.EntityType.GetTableName();
|
||||
getters = ps.Select(p => p.GetGetter());
|
||||
var colNames = ps.Select(p => $"\"{p.GetColumnBaseName()}\"");
|
||||
colunmsString = $"({string.Join(", ", colNames)})";
|
||||
conflictUpdateSet = string.Join(", ", colNames.Select(n => $"{n} = excluded.{n}"));
|
||||
var colunmsString = $"({string.Join(", ", colNames)})";
|
||||
|
||||
insertHeader = $"INSERT INTO {tableName} {colunmsString} VALUES ";
|
||||
var excludedUpdateSet = string.Join(", ", colNames.Select(n => $"{n} = excluded.{n}"));
|
||||
conflictBody = $" ON CONFLICT {pk} DO UPDATE SET {excludedUpdateSet};";
|
||||
}
|
||||
|
||||
public string MakeInsertOrUpdateSql(IEnumerable<T> items)
|
||||
@ -69,37 +74,35 @@ namespace AsbCloudDb
|
||||
SET column_1 = excluded.column_1,
|
||||
column_2 = excluded.column_2;
|
||||
*/
|
||||
var sqlBuilder = new StringBuilder("INSERT INTO ", 7);
|
||||
sqlBuilder.Append(tableName);
|
||||
sqlBuilder.Append(colunmsString);
|
||||
sqlBuilder.AppendLine(" VALUES ");
|
||||
sqlBuilder.Append(MakeQueryValues(items));
|
||||
sqlBuilder.AppendLine(" ON CONFLICT ");
|
||||
var builder = new StringBuilder(insertHeader, 7);
|
||||
BuildRows(builder, items);
|
||||
if (string.IsNullOrEmpty(pk))
|
||||
{
|
||||
sqlBuilder.Append("DO NOTHING;");
|
||||
}
|
||||
builder.Append(" ON CONFLICT DO NOTHING;");
|
||||
else
|
||||
{
|
||||
sqlBuilder.Append(pk);
|
||||
sqlBuilder.Append(" DO UPDATE SET ");
|
||||
sqlBuilder.AppendLine(conflictUpdateSet);
|
||||
sqlBuilder.Append(';');
|
||||
}
|
||||
builder.AppendLine(conflictBody);
|
||||
|
||||
return sqlBuilder.ToString();
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private string MakeQueryValues(IEnumerable<T> items)
|
||||
private StringBuilder BuildRows(StringBuilder builder, IEnumerable<T> items)
|
||||
{
|
||||
var rows = items.Select(item => MakeRow(item));
|
||||
return string.Join(",", rows);
|
||||
var list = items.ToList();
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
if(i > 0)
|
||||
builder.Append(',');
|
||||
BuildRow(builder, list[i]);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private string MakeRow(T item)
|
||||
private StringBuilder BuildRow(StringBuilder builder, T item)
|
||||
{
|
||||
var values = getters.Select(getter => FormatValue(getter.GetClrValue(item)));
|
||||
return $"({string.Join(",", values)})";
|
||||
builder.Append('(');
|
||||
builder.AppendJoin(",", values);
|
||||
builder.Append(')');
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static string FormatValue(object v)
|
||||
|
@ -18,7 +18,27 @@ namespace ConsoleApp1
|
||||
class Program
|
||||
{
|
||||
static void Main(/*string[] args*/)
|
||||
{
|
||||
{
|
||||
//var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
||||
// .UseNpgsql("Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True")
|
||||
// .Options;
|
||||
//var context = new AsbCloudDbContext(options);
|
||||
|
||||
//var sett = context.Set<TelemetryDataSaub>();
|
||||
//var r = context.Database.ExecInsertOrUpdateAsync(sett, new List<TelemetryDataSaub> {
|
||||
// new TelemetryDataSaub
|
||||
// {
|
||||
// Date = DateTime.Now,
|
||||
// IdTelemetry = 3,
|
||||
// AxialLoad = 100.1f,
|
||||
// },
|
||||
// new TelemetryDataSaub
|
||||
// {
|
||||
// Date = DateTime.Now.AddSeconds(2),
|
||||
// IdTelemetry = 3,
|
||||
// AxialLoad = 100.2f,
|
||||
// },
|
||||
//}, System.Threading.CancellationToken.None).Result;
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user