Skip to content

Commit

Permalink
Fix build after merge
Browse files Browse the repository at this point in the history
  • Loading branch information
bergmania committed Oct 29, 2021
1 parent 02bf616 commit bf5f136
Show file tree
Hide file tree
Showing 13 changed files with 1,017 additions and 910 deletions.
45 changes: 12 additions & 33 deletions src/Umbraco.Core/Collections/StackQueue.cs
Original file line number Diff line number Diff line change
@@ -1,60 +1,39 @@
using System.Collections.Generic;

namespace Umbraco.Core.Collections
namespace Umbraco.Cms.Core.Collections
{
/// <summary>
/// Collection that can be both a queue and a stack.
/// Collection that can be both a queue and a stack.
/// </summary>
/// <typeparam name="T"></typeparam>
public class StackQueue<T>
{
private readonly LinkedList<T> _linkedList = new LinkedList<T>();
private readonly LinkedList<T> _linkedList = new();

public void Clear()
{
_linkedList.Clear();
}
public int Count => _linkedList.Count;

public void Push(T obj)
{
_linkedList.AddFirst(obj);
}
public void Clear() => _linkedList.Clear();

public void Enqueue(T obj)
{
_linkedList.AddFirst(obj);
}
public void Push(T obj) => _linkedList.AddFirst(obj);

public void Enqueue(T obj) => _linkedList.AddFirst(obj);

public T Pop()
{
var obj = _linkedList.First.Value;
T obj = _linkedList.First.Value;
_linkedList.RemoveFirst();
return obj;
}

public T Dequeue()
{
var obj = _linkedList.Last.Value;
T obj = _linkedList.Last.Value;
_linkedList.RemoveLast();
return obj;
}

public T PeekStack()
{
return _linkedList.First.Value;
}
public T PeekStack() => _linkedList.First.Value;

public T PeekQueue()
{
return _linkedList.Last.Value;
}

public int Count
{
get
{
return _linkedList.Count;
}
}
public T PeekQueue() => _linkedList.Last.Value;
}
}
Original file line number Diff line number Diff line change
@@ -1,64 +1,76 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using NPoco;
using Umbraco.Cms.Core;
using Umbraco.Cms.Infrastructure.Persistence;

namespace Umbraco.Extensions
{
/// <summary>
/// Provides extension methods to NPoco Database class.
/// Provides extension methods to NPoco Database class.
/// </summary>
public static partial class NPocoDatabaseExtensions
{
/// <summary>
/// Configures NPoco's SqlBulkCopyHelper to use the correct SqlConnection and SqlTransaction instances from the underlying RetryDbConnection and ProfiledDbTransaction
/// Configures NPoco's SqlBulkCopyHelper to use the correct SqlConnection and SqlTransaction instances from the
/// underlying RetryDbConnection and ProfiledDbTransaction
/// </summary>
/// <remarks>
/// This is required to use NPoco's own <see cref="Database.InsertBulk{T}(IEnumerable{T})" /> method because we use wrapped DbConnection and DbTransaction instances.
/// NPoco's InsertBulk method only caters for efficient bulk inserting records for Sql Server, it does not cater for bulk inserting of records for
/// any other database type and in which case will just insert records one at a time.
/// NPoco's InsertBulk method also deals with updating the passed in entity's PK/ID once it's inserted whereas our own BulkInsertRecords methods
/// do not handle this scenario.
/// This is required to use NPoco's own <see cref="Database.InsertBulk{T}(IEnumerable{T})" /> method because we use
/// wrapped DbConnection and DbTransaction instances.
/// NPoco's InsertBulk method only caters for efficient bulk inserting records for Sql Server, it does not cater for
/// bulk inserting of records for
/// any other database type and in which case will just insert records one at a time.
/// NPoco's InsertBulk method also deals with updating the passed in entity's PK/ID once it's inserted whereas our own
/// BulkInsertRecords methods
/// do not handle this scenario.
/// </remarks>
public static void ConfigureNPocoBulkExtensions()
{

SqlBulkCopyHelper.SqlConnectionResolver = dbConn => GetTypedConnection<SqlConnection>(dbConn);
SqlBulkCopyHelper.SqlTransactionResolver = dbTran => GetTypedTransaction<SqlTransaction>(dbTran);
}


/// <summary>
/// Creates bulk-insert commands.
/// Creates bulk-insert commands.
/// </summary>
/// <typeparam name="T">The type of the records.</typeparam>
/// <param name="database">The database.</param>
/// <param name="records">The records.</param>
/// <returns>The sql commands to execute.</returns>
internal static IDbCommand[] GenerateBulkInsertCommands<T>(this IUmbracoDatabase database, T[] records)
{
if (database?.Connection == null) throw new ArgumentException("Null database?.connection.", nameof(database));
if (database?.Connection == null)
{
throw new ArgumentException("Null database?.connection.", nameof(database));
}

var pocoData = database.PocoDataFactory.ForType(typeof(T));
PocoData pocoData = database.PocoDataFactory.ForType(typeof(T));

// get columns to include, = number of parameters per row
var columns = pocoData.Columns.Where(c => IncludeColumn(pocoData, c)).ToArray();
KeyValuePair<string, PocoColumn>[] columns =
pocoData.Columns.Where(c => IncludeColumn(pocoData, c)).ToArray();
var paramsPerRecord = columns.Length;

// format columns to sql
var tableName = database.DatabaseType.EscapeTableName(pocoData.TableInfo.TableName);
var columnNames = string.Join(", ", columns.Select(c => tableName + "." + database.DatabaseType.EscapeSqlIdentifier(c.Key)));
var columnNames = string.Join(", ",
columns.Select(c => tableName + "." + database.DatabaseType.EscapeSqlIdentifier(c.Key)));

// example:
// assume 4168 records, each record containing 8 fields, ie 8 command parameters
// max 2100 parameter per command
// Math.Floor(2100 / 8) = 262 record per command
// 4168 / 262 = 15.908... = there will be 16 command in total
// (if we have disabled db parameters, then all records will be included, in only one command)
var recordsPerCommand = paramsPerRecord == 0 ? int.MaxValue : Convert.ToInt32(Math.Floor(2000.00 / paramsPerRecord));
var recordsPerCommand = paramsPerRecord == 0
? int.MaxValue
: Convert.ToInt32(Math.Floor((double)Constants.Sql.MaxParameterCount / paramsPerRecord));
var commandsCount = Convert.ToInt32(Math.Ceiling((double)records.Length / recordsPerCommand));

var commands = new IDbCommand[commandsCount];
Expand All @@ -67,43 +79,42 @@ internal static IDbCommand[] GenerateBulkInsertCommands<T>(this IUmbracoDatabase
var prefix = database.DatabaseType.GetParameterPrefix(database.ConnectionString);
for (var commandIndex = 0; commandIndex < commandsCount; commandIndex++)
{
var command = database.CreateCommand(database.Connection, CommandType.Text, string.Empty);
DbCommand command = database.CreateCommand(database.Connection, CommandType.Text, string.Empty);
var parameterIndex = 0;
var commandRecords = Math.Min(recordsPerCommand, recordsLeftToInsert);
var recordsValues = new string[commandRecords];
for (var commandRecordIndex = 0; commandRecordIndex < commandRecords; commandRecordIndex++, recordsIndex++, recordsLeftToInsert--)
for (var commandRecordIndex = 0;
commandRecordIndex < commandRecords;
commandRecordIndex++, recordsIndex++, recordsLeftToInsert--)
{
var record = records[recordsIndex];
T record = records[recordsIndex];
var recordValues = new string[columns.Length];
for (var columnIndex = 0; columnIndex < columns.Length; columnIndex++)
{
database.AddParameter(command, columns[columnIndex].Value.GetValue(record));
recordValues[columnIndex] = prefix + parameterIndex++;
}

recordsValues[commandRecordIndex] = "(" + string.Join(",", recordValues) + ")";
}

command.CommandText = $"INSERT INTO {tableName} ({columnNames}) VALUES {string.Join(", ", recordsValues)}";
command.CommandText =
$"INSERT INTO {tableName} ({columnNames}) VALUES {string.Join(", ", recordsValues)}";
commands[commandIndex] = command;
}

return commands;
}

/// <summary>
/// Determines whether a column should be part of a bulk-insert.
/// Determines whether a column should be part of a bulk-insert.
/// </summary>
/// <param name="pocoData">The PocoData object corresponding to the record's type.</param>
/// <param name="column">The column.</param>
/// <returns>A value indicating whether the column should be part of the bulk-insert.</returns>
/// <remarks>Columns that are primary keys and auto-incremental, or result columns, are excluded from bulk-inserts.</remarks>
public static bool IncludeColumn(PocoData pocoData, KeyValuePair<string, PocoColumn> column)
{
return column.Value.ResultColumn == false
&& (pocoData.TableInfo.AutoIncrement == false || column.Key != pocoData.TableInfo.PrimaryKey);
}



public static bool IncludeColumn(PocoData pocoData, KeyValuePair<string, PocoColumn> column) =>
column.Value.ResultColumn == false
&& (pocoData.TableInfo.AutoIncrement == false || column.Key != pocoData.TableInfo.PrimaryKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using Microsoft.Extensions.Logging;
using NPoco;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Persistence.Querying;
Expand All @@ -16,26 +17,47 @@
namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
{
/// <summary>
/// Represents the NPoco implementation of <see cref="IAuditEntryRepository"/>.
/// Represents the NPoco implementation of <see cref="IAuditEntryRepository" />.
/// </summary>
internal class AuditEntryRepository : EntityRepositoryBase<int, IAuditEntry>, IAuditEntryRepository
{
/// <summary>
/// Initializes a new instance of the <see cref="AuditEntryRepository"/> class.
/// Initializes a new instance of the <see cref="AuditEntryRepository" /> class.
/// </summary>
public AuditEntryRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger<AuditEntryRepository> logger)
: base(scopeAccessor, cache, logger)
{ }
{
}

/// <inheritdoc />
public IEnumerable<IAuditEntry> GetPage(long pageIndex, int pageCount, out long records)
{
Sql<ISqlContext> sql = Sql()
.Select<AuditEntryDto>()
.From<AuditEntryDto>()
.OrderByDescending<AuditEntryDto>(x => x.EventDateUtc);

Page<AuditEntryDto> page = Database.Page<AuditEntryDto>(pageIndex + 1, pageCount, sql);
records = page.TotalItems;
return page.Items.Select(AuditEntryFactory.BuildEntity);
}

/// <inheritdoc />
public bool IsAvailable()
{
var tables = SqlSyntax.GetTablesInSchema(Database).ToArray();
return tables.InvariantContains(Constants.DatabaseSchema.Tables.AuditEntry);
}

/// <inheritdoc />
protected override IAuditEntry PerformGet(int id)
{
var sql = Sql()
Sql<ISqlContext> sql = Sql()
.Select<AuditEntryDto>()
.From<AuditEntryDto>()
.Where<AuditEntryDto>(x => x.Id == id);

var dto = Database.FirstOrDefault<AuditEntryDto>(sql);
AuditEntryDto dto = Database.FirstOrDefault<AuditEntryDto>(sql);
return dto == null ? null : AuditEntryFactory.BuildEntity(dto);
}

Expand All @@ -44,7 +66,7 @@ protected override IEnumerable<IAuditEntry> PerformGetAll(params int[] ids)
{
if (ids.Length == 0)
{
var sql = Sql()
Sql<ISqlContext> sql = Sql()
.Select<AuditEntryDto>()
.From<AuditEntryDto>();

Expand All @@ -53,9 +75,9 @@ protected override IEnumerable<IAuditEntry> PerformGetAll(params int[] ids)

var entries = new List<IAuditEntry>();

foreach (var group in ids.InGroupsOf(Constants.Sql.MaxParameterCount))
foreach (IEnumerable<int> group in ids.InGroupsOf(Constants.Sql.MaxParameterCount))
{
var sql = Sql()
Sql<ISqlContext> sql = Sql()
.Select<AuditEntryDto>()
.From<AuditEntryDto>()
.WhereIn<AuditEntryDto>(x => x.Id, group);
Expand All @@ -69,68 +91,41 @@ protected override IEnumerable<IAuditEntry> PerformGetAll(params int[] ids)
/// <inheritdoc />
protected override IEnumerable<IAuditEntry> PerformGetByQuery(IQuery<IAuditEntry> query)
{
var sqlClause = GetBaseQuery(false);
Sql<ISqlContext> sqlClause = GetBaseQuery(false);
var translator = new SqlTranslator<IAuditEntry>(sqlClause, query);
var sql = translator.Translate();
Sql<ISqlContext> sql = translator.Translate();
return Database.Fetch<AuditEntryDto>(sql).Select(AuditEntryFactory.BuildEntity);
}

/// <inheritdoc />
protected override Sql<ISqlContext> GetBaseQuery(bool isCount)
{
var sql = Sql();
Sql<ISqlContext> sql = Sql();
sql = isCount ? sql.SelectCount() : sql.Select<AuditEntryDto>();
sql = sql.From<AuditEntryDto>();
return sql;
}

/// <inheritdoc />
protected override string GetBaseWhereClause()
{
return $"{Cms.Core.Constants.DatabaseSchema.Tables.AuditEntry}.id = @id";
}
protected override string GetBaseWhereClause() => $"{Constants.DatabaseSchema.Tables.AuditEntry}.id = @id";

/// <inheritdoc />
protected override IEnumerable<string> GetDeleteClauses()
{
protected override IEnumerable<string> GetDeleteClauses() =>
throw new NotSupportedException("Audit entries cannot be deleted.");
}

/// <inheritdoc />
protected override void PersistNewItem(IAuditEntry entity)
{
entity.AddingEntity();

var dto = AuditEntryFactory.BuildDto(entity);
AuditEntryDto dto = AuditEntryFactory.BuildDto(entity);
Database.Insert(dto);
entity.Id = dto.Id;
entity.ResetDirtyProperties();
}

/// <inheritdoc />
protected override void PersistUpdatedItem(IAuditEntry entity)
{
protected override void PersistUpdatedItem(IAuditEntry entity) =>
throw new NotSupportedException("Audit entries cannot be updated.");
}

/// <inheritdoc />
public IEnumerable<IAuditEntry> GetPage(long pageIndex, int pageCount, out long records)
{
var sql = Sql()
.Select<AuditEntryDto>()
.From<AuditEntryDto>()
.OrderByDescending<AuditEntryDto>(x => x.EventDateUtc);

var page = Database.Page<AuditEntryDto>(pageIndex + 1, pageCount, sql);
records = page.TotalItems;
return page.Items.Select(AuditEntryFactory.BuildEntity);
}

/// <inheritdoc />
public bool IsAvailable()
{
var tables = SqlSyntax.GetTablesInSchema(Database).ToArray();
return tables.InvariantContains(Cms.Core.Constants.DatabaseSchema.Tables.AuditEntry);
}
}
}
Loading

0 comments on commit bf5f136

Please sign in to comment.