diff --git a/Directory.Packages.props b/Directory.Packages.props
index 29e6149..ccecaf9 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,31 +4,32 @@
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/Tests/Benchmarks/AltaSoft.Storm.Benchmarks.csproj b/Tests/Benchmarks/AltaSoft.Storm.Benchmarks.csproj
index 098f730..af336b8 100644
--- a/Tests/Benchmarks/AltaSoft.Storm.Benchmarks.csproj
+++ b/Tests/Benchmarks/AltaSoft.Storm.Benchmarks.csproj
@@ -10,11 +10,11 @@
-
-
+
+
-
+
diff --git a/Tests/OrmTests/AltaSoft.Storm.Tests.csproj b/Tests/OrmTests/AltaSoft.Storm.Tests.csproj
index 633cba7..c545727 100644
--- a/Tests/OrmTests/AltaSoft.Storm.Tests.csproj
+++ b/Tests/OrmTests/AltaSoft.Storm.Tests.csproj
@@ -14,10 +14,10 @@
-
+
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/Tests/OrmTests/DeleteTopIntegrationTests.cs b/Tests/OrmTests/DeleteTopIntegrationTests.cs
new file mode 100644
index 0000000..446a43f
--- /dev/null
+++ b/Tests/OrmTests/DeleteTopIntegrationTests.cs
@@ -0,0 +1,87 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using AltaSoft.Storm.TestModels;
+using FluentAssertions;
+using Xunit;
+
+namespace AltaSoft.Storm.Tests;
+
+///
+/// End-to-end (real database) verification that DELETE ... Top(n) actually
+/// limits the number of deleted rows per call, instead of deleting every
+/// row that matches the WHERE clause.
+///
+public class DeleteTopIntegrationTests : IClassFixture, IAsyncLifetime
+{
+ private const int BatchSize = 10;
+ private const int TotalUsers = 100;
+ private const int FirstUserId = 1000;
+
+ private readonly TestStormContext _context;
+
+ public DeleteTopIntegrationTests(DatabaseFixture fixture)
+ {
+ _context = new TestStormContext(fixture.ConnectionString);
+ }
+
+ public async Task InitializeAsync()
+ {
+ // Inserted in small batches - a single 100-row batch with all of User's
+ // detail-table columns (Cars, Dates, lists, ...) exceeds SQL Server's
+ // 2100-parameter-per-request limit.
+ const int insertBatchSize = 10;
+ for (var batchStart = 0; batchStart < TotalUsers; batchStart += insertBatchSize)
+ {
+ var batch = new List(insertBatchSize);
+ for (var i = batchStart; i < batchStart + insertBatchSize; i++)
+ {
+ batch.Add(DatabaseHelper.NewUser(FirstUserId + i));
+ }
+
+ await _context.InsertIntoUsersTable().Values(batch).GoAsync();
+ }
+ }
+
+ [Fact]
+ public async Task DeleteWithTop_RemovesExactlyTopRowsPerCall_UntilNoneLeft()
+ {
+ // Sanity check: all 100 rows were inserted
+ var remainingBeforeDelete = await _context.SelectFromUsersTable()
+ .Where(x => x.UserId >= FirstUserId)
+ .ListAsync();
+ remainingBeforeDelete.Should().HaveCount(TotalUsers);
+
+ var iterations = 0;
+ var totalDeleted = 0;
+
+ while (true)
+ {
+ var deletedCount = await _context.DeleteFromUsersTable()
+ .Where(x => x.UserId >= FirstUserId)
+ .Top(BatchSize)
+ .GoAsync();
+
+ if (deletedCount == 0)
+ break;
+
+ // Every call must delete exactly BatchSize rows, never more.
+ deletedCount.Should().Be(BatchSize);
+
+ iterations++;
+ totalDeleted += deletedCount;
+ }
+
+ iterations.Should().Be(TotalUsers / BatchSize);
+ totalDeleted.Should().Be(TotalUsers);
+
+ var remainingAfterDelete = await _context.SelectFromUsersTable()
+ .Where(x => x.UserId >= FirstUserId)
+ .ListAsync();
+ remainingAfterDelete.Should().BeEmpty();
+ }
+
+ public async Task DisposeAsync()
+ {
+ await _context.DisposeAsync().ConfigureAwait(false);
+ }
+}
diff --git a/Tests/OrmTests/ODataFilterStatementGeneratorTests.cs b/Tests/OrmTests/ODataFilterStatementGeneratorTests.cs
new file mode 100644
index 0000000..bb9d1e6
--- /dev/null
+++ b/Tests/OrmTests/ODataFilterStatementGeneratorTests.cs
@@ -0,0 +1,185 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Text;
+using System.Threading.Tasks;
+using AltaSoft.Storm.Crud;
+using AltaSoft.Storm.Extensions;
+using AltaSoft.Storm.Helpers;
+using AltaSoft.Storm.TestModels;
+using FluentAssertions;
+using Microsoft.Data.SqlClient;
+using Xunit;
+using Xunit.Abstractions;
+using StormDbParameter = Microsoft.Data.SqlClient.SqlParameter;
+
+namespace AltaSoft.Storm.Tests;
+
+///
+/// Verifies that OData $filter expressions are translated to parameterized SQL correctly,
+/// specifically for DateOnly and TimeOnly properties (Edm.Date / Edm.TimeOfDay).
+///
+/// Mirrors SqlStatementGeneratorTests, but drives the OData filter generator
+/// (ODataFilterStatementGenerator.GenerateSql) instead of LINQ where-expressions.
+/// No database connection is opened - only the SQL-generation pipeline runs.
+///
+public class ODataFilterStatementGeneratorTests : IClassFixture, IAsyncLifetime
+{
+ private readonly TestStormContext _context;
+
+ public ODataFilterStatementGeneratorTests(DatabaseFixture fixture, ITestOutputHelper output)
+ {
+ var logger = new XunitLogger(output);
+
+ StormManager.SetLogger(logger);
+
+ _context = new TestStormContext(fixture.ConnectionString);
+ }
+
+ public Task InitializeAsync() => Task.CompletedTask;
+
+ public async Task DisposeAsync() => await _context.DisposeAsync().ConfigureAwait(false);
+
+ private sealed class FakeCommand : IVirtualStormDbCommand
+ {
+ public readonly List<(string Name, UnifiedDbType DbType, int Size, object? Value)> Params = [];
+ public string CommandText { get; set; } = string.Empty;
+ public CommandType CommandType { get; set; }
+
+ public string AddDbParameter(int paramIdx, StormColumnDef column, object? value)
+ {
+ var name = "@p" + paramIdx.ToString(System.Globalization.CultureInfo.InvariantCulture);
+ Params.Add((name, column.DbType, column.Size, value));
+ return name;
+ }
+
+ public StormDbParameter AddDbParameter(string paramName, UnifiedDbType dbType, int size, object? value)
+ {
+ Params.Add((paramName, dbType, size, value));
+ return default!;
+ }
+
+ public void AddDbParameters(List callParameters) { }
+
+ public void SetStormCommandBaseParameters(SqlConnection connection, SqlTransaction? transaction, string sql,
+ QueryParameters queryParameters, CommandType commandType = CommandType.Text) => throw new NotImplementedException();
+
+ public void SetStormCommandBaseParameters(string sql, QueryParameters queryParameters,
+ CommandType commandType = CommandType.Text) => throw new NotImplementedException();
+
+ public void SetStormCommandBaseParameters(SqlConnection connection, SqlTransaction? transaction) => throw new NotImplementedException();
+
+ public string? GenerateCallParameters(List? queryParametersCallParameters, CallParameterType type) => null;
+ }
+
+ private static (string sql, FakeCommand cmd) RunODataFilter(string filter, StormColumnDef[] columns)
+ {
+ var sb = new StringBuilder();
+ var cmd = new FakeCommand();
+ var idx = 0;
+ ODataFilterStatementGenerator.GenerateSql(cmd, filter, columns, null, ref idx, sb);
+ return (sb.ToString(), cmd);
+ }
+
+ [Fact]
+ public void DateOnly_Equal_ShouldGenerateParameterAndSql()
+ {
+ var ctrl = StormControllerCache.Get(0);
+ var cols = ctrl.ColumnDefs;
+
+ var (sql, cmd) = RunODataFilter("DateValue eq 2024-05-17", cols);
+
+ sql.Should().Be("[DateValue] = @p0");
+ cmd.Params.Should().HaveCount(1);
+ cmd.Params[0].DbType.Should().Be(UnifiedDbType.Date);
+ cmd.Params[0].Value.Should().Be(new DateOnly(2024, 5, 17));
+ }
+
+ [Fact]
+ public void DateOnly_GreaterThan_ShouldGenerateParameterAndSql()
+ {
+ var ctrl = StormControllerCache.Get(0);
+ var cols = ctrl.ColumnDefs;
+
+ var (sql, cmd) = RunODataFilter("DateValue gt 2024-01-01", cols);
+
+ sql.Should().Be("[DateValue] > @p0");
+ cmd.Params.Should().HaveCount(1);
+ cmd.Params[0].Value.Should().Be(new DateOnly(2024, 1, 1));
+ }
+
+ [Fact]
+ public void NullableDateOnly_EqualNull_ShouldGenerateIsNull()
+ {
+ var ctrl = StormControllerCache.Get(0);
+ var cols = ctrl.ColumnDefs;
+
+ var (sql, cmd) = RunODataFilter("DateValueN eq null", cols);
+
+ sql.Should().Be("[DateValueN] IS NULL");
+ cmd.Params.Should().BeEmpty();
+ }
+
+ [Fact]
+ public void NullableDateOnly_NotEqualNull_ShouldGenerateIsNotNull()
+ {
+ var ctrl = StormControllerCache.Get(0);
+ var cols = ctrl.ColumnDefs;
+
+ var (sql, cmd) = RunODataFilter("DateValueN ne null", cols);
+
+ sql.Should().Be("[DateValueN] IS NOT NULL");
+ cmd.Params.Should().BeEmpty();
+ }
+
+ [Fact]
+ public void TimeOnly_Equal_ShouldGenerateParameterAndSql()
+ {
+ var ctrl = StormControllerCache.Get(0);
+ var cols = ctrl.ColumnDefs;
+
+ var (sql, cmd) = RunODataFilter("TimeValue eq 13:45:30", cols);
+
+ sql.Should().Be("[TimeValue] = @p0");
+ cmd.Params.Should().HaveCount(1);
+ cmd.Params[0].DbType.Should().Be(UnifiedDbType.Time);
+ cmd.Params[0].Value.Should().Be(new TimeOnly(13, 45, 30));
+ }
+
+ [Fact]
+ public void TimeOnly_LessThan_ShouldGenerateParameterAndSql()
+ {
+ var ctrl = StormControllerCache.Get(0);
+ var cols = ctrl.ColumnDefs;
+
+ var (sql, cmd) = RunODataFilter("TimeValue lt 08:30:00", cols);
+
+ sql.Should().Be("[TimeValue] < @p0");
+ cmd.Params.Should().HaveCount(1);
+ cmd.Params[0].Value.Should().Be(new TimeOnly(8, 30, 0));
+ }
+
+ [Fact]
+ public void NullableTimeOnly_EqualNull_ShouldGenerateIsNull()
+ {
+ var ctrl = StormControllerCache.Get(0);
+ var cols = ctrl.ColumnDefs;
+
+ var (sql, cmd) = RunODataFilter("TimeValueN eq null", cols);
+
+ sql.Should().Be("[TimeValueN] IS NULL");
+ cmd.Params.Should().BeEmpty();
+ }
+
+ [Fact]
+ public void NullableTimeOnly_NotEqualNull_ShouldGenerateIsNotNull()
+ {
+ var ctrl = StormControllerCache.Get(0);
+ var cols = ctrl.ColumnDefs;
+
+ var (sql, cmd) = RunODataFilter("TimeValueN ne null", cols);
+
+ sql.Should().Be("[TimeValueN] IS NOT NULL");
+ cmd.Params.Should().BeEmpty();
+ }
+}
diff --git a/Tests/OrmTests/TopClauseSqlGenerationTests.cs b/Tests/OrmTests/TopClauseSqlGenerationTests.cs
new file mode 100644
index 0000000..0a115e9
--- /dev/null
+++ b/Tests/OrmTests/TopClauseSqlGenerationTests.cs
@@ -0,0 +1,70 @@
+using System.Collections.Generic;
+using AltaSoft.Storm.Crud;
+using AltaSoft.Storm.TestModels;
+using FluentAssertions;
+using Microsoft.Data.SqlClient;
+using Xunit;
+
+namespace AltaSoft.Storm.Tests;
+
+///
+/// Verifies that Top(n) on DELETE / UPDATE actually writes a TOP (n) clause
+/// into the generated SQL string, instead of being silently ignored.
+///
+/// Uses GenerateBatchCommands() instead of GoAsync() — the full SQL-generation
+/// pipeline runs without opening a database connection, so the CommandText of
+/// every SqlBatchCommand can be inspected directly.
+/// IClassFixture<DatabaseFixture> is kept only to guarantee StormManager is
+/// initialized before the first test runs.
+///
+public class TopClauseSqlGenerationTests : IClassFixture
+{
+ private readonly TestStormContext _context;
+
+ public TopClauseSqlGenerationTests(DatabaseFixture fixture)
+ {
+ _context = new TestStormContext(fixture.ConnectionString);
+ }
+
+ private static string Sql(ISqlGo command)
+ {
+ var batch = new List();
+ command.GenerateBatchCommands(batch);
+ batch.Should().NotBeEmpty("GenerateBatchCommands must produce at least one command");
+ return batch[0].CommandText;
+ }
+
+ [Fact]
+ public void Delete_Where_WithTop_SqlContainsTopClause()
+ {
+ var sql = Sql(_context.DeleteFromUsersTable()
+ .Where(x => x.UserId == 1)
+ .Top(100));
+
+ sql.Should().Contain("TOP (100)", "Top(100) on a DELETE must be reflected in the generated SQL");
+ }
+
+ [Fact]
+ public void Delete_Where_WithTop_TopClauseAppearsRightAfterDeleteFrom()
+ {
+ var sql = Sql(_context.DeleteFromUsersTable()
+ .Where(x => x.UserId == 1)
+ .Top(100));
+
+ var deletePos = sql.IndexOf("DELETE FROM", System.StringComparison.OrdinalIgnoreCase);
+ var topPos = sql.IndexOf("TOP (100)", System.StringComparison.OrdinalIgnoreCase);
+
+ deletePos.Should().BeGreaterThanOrEqualTo(0);
+ topPos.Should().BeGreaterThan(deletePos, "TOP clause must come after DELETE FROM");
+ }
+
+ [Fact]
+ public void Update_SetInstruction_WithTop_SqlContainsTopClause()
+ {
+ var sql = Sql(_context.UpdateUsersTable()
+ .Set(x => x.FullName, "test")
+ .Top(100));
+
+ sql.Should().Contain("TOP (100)", "Top(100) on an UPDATE must be reflected in the generated SQL");
+ }
+}
diff --git a/Tests/TestModels/AltaSoft.Storm.TestModels.csproj b/Tests/TestModels/AltaSoft.Storm.TestModels.csproj
index 4b37aee..4453544 100644
--- a/Tests/TestModels/AltaSoft.Storm.TestModels.csproj
+++ b/Tests/TestModels/AltaSoft.Storm.TestModels.csproj
@@ -25,11 +25,11 @@
-
-
+
+
compile; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyId.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyId.g.cs
index 42cb6f5..8559801 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyId.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyId.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using System;
using System.Numerics;
using System.Diagnostics;
@@ -67,7 +75,7 @@ public CurrencyId()
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
///
- /// Tries to create an instance of AsciiString from the specified value.
+ /// Tries to create an instance of CurrencyId from the specified value.
///
/// The value to create CurrencyId from
/// When this method returns, contains the created CurrencyId if the conversion succeeded, or null if the conversion failed.
@@ -78,13 +86,13 @@ public static bool TryCreate(string value, [NotNullWhen(true)] out CurrencyId? r
}
///
- /// Tries to create an instance of AsciiString from the specified value.
+ /// Tries to create an instance of CurrencyId from the specified value.
///
/// The value to create CurrencyId from
/// When this method returns, contains the created CurrencyId if the conversion succeeded, or null if the conversion failed.
/// When this method returns, contains the error message if the conversion failed; otherwise, null.
/// true if the conversion succeeded; otherwise, false.
- public static bool TryCreate(string value, [NotNullWhen(true)] out CurrencyId? result, [NotNullWhen(false)] out string? errorMessage)
+ public static bool TryCreate(string value, [NotNullWhen(true)] out CurrencyId? result, [NotNullWhen(false)] out string? errorMessage)
{
var validationResult = Validate(value);
if (!validationResult.IsValid)
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyIdJsonConverter.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyIdJsonConverter.g.cs
index 56748f9..45b07e8 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyIdJsonConverter.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyIdJsonConverter.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using AltaSoft.Storm.TestModels.VeryBadNamespace;
using System;
using System.Text.Json;
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyIdTypeConverter.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyIdTypeConverter.g.cs
index 433bad7..4b11715 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyIdTypeConverter.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CurrencyIdTypeConverter.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using AltaSoft.Storm.TestModels.VeryBadNamespace;
using System;
using System.ComponentModel;
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerId.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerId.g.cs
index c33f27b..a8a8878 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerId.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerId.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using System;
using System.Numerics;
using System.Diagnostics;
@@ -74,7 +82,7 @@ public CustomerId()
}
///
- /// Tries to create an instance of AsciiString from the specified value.
+ /// Tries to create an instance of CustomerId from the specified value.
///
/// The value to create CustomerId from
/// When this method returns, contains the created CustomerId if the conversion succeeded, or null if the conversion failed.
@@ -85,13 +93,13 @@ public static bool TryCreate(long value, [NotNullWhen(true)] out CustomerId? res
}
///
- /// Tries to create an instance of AsciiString from the specified value.
+ /// Tries to create an instance of CustomerId from the specified value.
///
/// The value to create CustomerId from
/// When this method returns, contains the created CustomerId if the conversion succeeded, or null if the conversion failed.
/// When this method returns, contains the error message if the conversion failed; otherwise, null.
/// true if the conversion succeeded; otherwise, false.
- public static bool TryCreate(long value, [NotNullWhen(true)] out CustomerId? result, [NotNullWhen(false)] out string? errorMessage)
+ public static bool TryCreate(long value, [NotNullWhen(true)] out CustomerId? result, [NotNullWhen(false)] out string? errorMessage)
{
var validationResult = Validate(value);
if (!validationResult.IsValid)
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerIdJsonConverter.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerIdJsonConverter.g.cs
index e22166e..59ed8df 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerIdJsonConverter.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerIdJsonConverter.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using AltaSoft.Storm.TestModels.VeryBadNamespace;
using System;
using System.Text.Json;
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerIdTypeConverter.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerIdTypeConverter.g.cs
index 66937e9..9526e47 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerIdTypeConverter.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/CustomerIdTypeConverter.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using AltaSoft.Storm.TestModels.VeryBadNamespace;
using System;
using System.ComponentModel;
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/OpenApiHelper.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/OpenApiHelper.g.cs
index 3af0375..ea206b1 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/OpenApiHelper.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/OpenApiHelper.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using AltaSoft.Storm.TestModels.VeryBadNamespace;
using AltaSoft.Storm.TestModels.DomainTypes;
using Microsoft.OpenApi;
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserId.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserId.g.cs
index c47e57a..6befb17 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserId.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserId.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using System;
using System.Numerics;
using System.Diagnostics;
@@ -74,7 +82,7 @@ public UserId()
}
///
- /// Tries to create an instance of AsciiString from the specified value.
+ /// Tries to create an instance of UserId from the specified value.
///
/// The value to create UserId from
/// When this method returns, contains the created UserId if the conversion succeeded, or null if the conversion failed.
@@ -85,13 +93,13 @@ public static bool TryCreate(int value, [NotNullWhen(true)] out UserId? result)
}
///
- /// Tries to create an instance of AsciiString from the specified value.
+ /// Tries to create an instance of UserId from the specified value.
///
/// The value to create UserId from
/// When this method returns, contains the created UserId if the conversion succeeded, or null if the conversion failed.
/// When this method returns, contains the error message if the conversion failed; otherwise, null.
/// true if the conversion succeeded; otherwise, false.
- public static bool TryCreate(int value, [NotNullWhen(true)] out UserId? result, [NotNullWhen(false)] out string? errorMessage)
+ public static bool TryCreate(int value, [NotNullWhen(true)] out UserId? result, [NotNullWhen(false)] out string? errorMessage)
{
var validationResult = Validate(value);
if (!validationResult.IsValid)
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserIdJsonConverter.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserIdJsonConverter.g.cs
index 63d0a23..cf29d25 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserIdJsonConverter.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserIdJsonConverter.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using AltaSoft.Storm.TestModels.DomainTypes;
using System;
using System.Text.Json;
diff --git a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserIdTypeConverter.g.cs b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserIdTypeConverter.g.cs
index 244f9be..d3cc130 100644
--- a/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserIdTypeConverter.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.DomainPrimitives.Generator/AltaSoft.DomainPrimitives.Generator.DomainPrimitiveGenerator/UserIdTypeConverter.g.cs
@@ -7,6 +7,14 @@
#nullable enable
+#pragma warning disable CS8774 // Member must have a non-null value when exiting.
+#pragma warning disable CS0628 // New protected member declared in sealed type
+#pragma warning disable CS0612 // Type or member is obsolete
+#pragma warning disable CS0618 // Type or member is obsolete
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable IDE0290 // Use primary constructor
+
using AltaSoft.Storm.TestModels.DomainTypes;
using System;
using System.ComponentModel;
diff --git a/Tests/TestModels/Generated/AltaSoft.Storm.Generator/AltaSoft.Storm.Generator.StormGenerator/SqlWhereTestEntity.g.cs b/Tests/TestModels/Generated/AltaSoft.Storm.Generator/AltaSoft.Storm.Generator.StormGenerator/SqlWhereTestEntity.g.cs
index e627bdb..bebc5b1 100644
--- a/Tests/TestModels/Generated/AltaSoft.Storm.Generator/AltaSoft.Storm.Generator.StormGenerator/SqlWhereTestEntity.g.cs
+++ b/Tests/TestModels/Generated/AltaSoft.Storm.Generator/AltaSoft.Storm.Generator.StormGenerator/SqlWhereTestEntity.g.cs
@@ -10,9 +10,9 @@
#nullable enable
+using System;
using AltaSoft.Storm.Attributes;
using AltaSoft.Storm.TestModels.VeryBadNamespace;
-using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
@@ -66,6 +66,10 @@ protected internal SqlWhereTestEntity(StormDbDataReader dr, uint partialLoadFlag
CcyN = (AltaSoft.Storm.TestModels.VeryBadNamespace.CurrencyId?)(string?)dr.GetStringOrNull(idx++);
BoolValue = (bool)dr.GetBoolean(idx++);
BoolValueN = (bool?)dr.GetBooleanOrNull(idx++);
+ DateValue = (System.DateOnly)dr.GetDate(idx++);
+ DateValueN = (System.DateOnly?)dr.GetDateOrNull(idx++);
+ TimeValue = (System.TimeOnly)dr.GetTime(idx++);
+ TimeValueN = (System.TimeOnly?)dr.GetTimeOrNull(idx++);
}
@@ -119,7 +123,15 @@ public enum OrderBy
BoolValue = 12,
BoolValue_Desc = -12,
BoolValueN = 13,
- BoolValueN_Desc = -13
+ BoolValueN_Desc = -13,
+ DateValue = 14,
+ DateValue_Desc = -14,
+ DateValueN = 15,
+ DateValueN_Desc = -15,
+ TimeValue = 16,
+ TimeValue_Desc = -16,
+ TimeValueN = 17,
+ TimeValueN_Desc = -17
}
///
@@ -151,7 +163,11 @@ public enum OrderBy
(columnDefs[9], (string)Ccy),
(columnDefs[10], (string?)CcyN),
(columnDefs[11], BoolValue),
- (columnDefs[12], BoolValueN)
+ (columnDefs[12], BoolValueN),
+ (columnDefs[13], (DateOnly)DateValue),
+ (columnDefs[14], (DateOnly?)DateValueN),
+ (columnDefs[15], (TimeOnly)TimeValue),
+ (columnDefs[16], (TimeOnly?)TimeValueN)
];
}
@@ -188,6 +204,10 @@ public virtual (string propertyName, IChangeTrackable? value)[] __TrackableMembe
private void __PropertySet_CcyN(ref AltaSoft.Storm.TestModels.VeryBadNamespace.CurrencyId? newValue, ref AltaSoft.Storm.TestModels.VeryBadNamespace.CurrencyId? oldValue) { if (_isChangeTrackingActive && oldValue != newValue) _changeTrackingStateMachine!.PropertyChanged(nameof(CcyN), newValue); }
private void __PropertySet_BoolValue(ref bool newValue, ref bool oldValue) { if (_isChangeTrackingActive && oldValue != newValue) _changeTrackingStateMachine!.PropertyChanged(nameof(BoolValue), newValue); }
private void __PropertySet_BoolValueN(ref bool? newValue, ref bool? oldValue) { if (_isChangeTrackingActive && oldValue != newValue) _changeTrackingStateMachine!.PropertyChanged(nameof(BoolValueN), newValue); }
+ private void __PropertySet_DateValue(ref System.DateOnly newValue, ref System.DateOnly oldValue) { if (_isChangeTrackingActive && oldValue != newValue) _changeTrackingStateMachine!.PropertyChanged(nameof(DateValue), newValue); }
+ private void __PropertySet_DateValueN(ref System.DateOnly? newValue, ref System.DateOnly? oldValue) { if (_isChangeTrackingActive && oldValue != newValue) _changeTrackingStateMachine!.PropertyChanged(nameof(DateValueN), newValue); }
+ private void __PropertySet_TimeValue(ref System.TimeOnly newValue, ref System.TimeOnly oldValue) { if (_isChangeTrackingActive && oldValue != newValue) _changeTrackingStateMachine!.PropertyChanged(nameof(TimeValue), newValue); }
+ private void __PropertySet_TimeValueN(ref System.TimeOnly? newValue, ref System.TimeOnly? oldValue) { if (_isChangeTrackingActive && oldValue != newValue) _changeTrackingStateMachine!.PropertyChanged(nameof(TimeValueN), newValue); }
#endregion Change Tracking Support
}
@@ -237,6 +257,10 @@ public override IDataBindable Create(StormDbDataReader dr, uint partialLoadFlags
nameof(SqlWhereTestEntity.CcyN) => (AltaSoft.Storm.TestModels.VeryBadNamespace.CurrencyId?)(string?)dr.GetStringOrNull(idx++),
nameof(SqlWhereTestEntity.BoolValue) => (bool)dr.GetBoolean(idx++),
nameof(SqlWhereTestEntity.BoolValueN) => (bool?)dr.GetBooleanOrNull(idx++),
+ nameof(SqlWhereTestEntity.DateValue) => (System.DateOnly)dr.GetDate(idx++),
+ nameof(SqlWhereTestEntity.DateValueN) => (System.DateOnly?)dr.GetDateOrNull(idx++),
+ nameof(SqlWhereTestEntity.TimeValue) => (System.TimeOnly)dr.GetTime(idx++),
+ nameof(SqlWhereTestEntity.TimeValueN) => (System.TimeOnly?)dr.GetTimeOrNull(idx++),
_ => throw new StormException($"'{propertyName}' is not a column of the table")
};
}
@@ -264,7 +288,11 @@ public override object CreateDetailRow(StormColumnDef column, StormDbDataReader
new(nameof(SqlWhereTestEntity.Ccy), null, "Ccy", StormColumnFlags.CanSelect | StormColumnFlags.CanInsert | StormColumnFlags.CanUpdate, UnifiedDbType.String, -1, 0, 0, SaveAs.Default, 0, false, null, null, typeof(AltaSoft.Storm.TestModels.VeryBadNamespace.CurrencyId), null),
new(nameof(SqlWhereTestEntity.CcyN), null, "CcyN", StormColumnFlags.CanSelect | StormColumnFlags.CanInsert | StormColumnFlags.CanUpdate, UnifiedDbType.String, -1, 0, 0, SaveAs.Default, 0, true, null, null, typeof(AltaSoft.Storm.TestModels.VeryBadNamespace.CurrencyId), null),
new(nameof(SqlWhereTestEntity.BoolValue), null, "BoolValue", StormColumnFlags.CanSelect | StormColumnFlags.CanInsert | StormColumnFlags.CanUpdate, UnifiedDbType.Boolean, 0, 0, 0, SaveAs.Default, 0, false, null, null, typeof(bool), null),
- new(nameof(SqlWhereTestEntity.BoolValueN), null, "BoolValueN", StormColumnFlags.CanSelect | StormColumnFlags.CanInsert | StormColumnFlags.CanUpdate, UnifiedDbType.Boolean, 0, 0, 0, SaveAs.Default, 0, true, null, null, typeof(bool), null)
+ new(nameof(SqlWhereTestEntity.BoolValueN), null, "BoolValueN", StormColumnFlags.CanSelect | StormColumnFlags.CanInsert | StormColumnFlags.CanUpdate, UnifiedDbType.Boolean, 0, 0, 0, SaveAs.Default, 0, true, null, null, typeof(bool), null),
+ new(nameof(SqlWhereTestEntity.DateValue), null, "DateValue", StormColumnFlags.CanSelect | StormColumnFlags.CanInsert | StormColumnFlags.CanUpdate, UnifiedDbType.Date, 0, 0, 0, SaveAs.Default, 0, false, null, null, typeof(System.DateOnly), null),
+ new(nameof(SqlWhereTestEntity.DateValueN), null, "DateValueN", StormColumnFlags.CanSelect | StormColumnFlags.CanInsert | StormColumnFlags.CanUpdate, UnifiedDbType.Date, 0, 0, 0, SaveAs.Default, 0, true, null, null, typeof(System.DateOnly), null),
+ new(nameof(SqlWhereTestEntity.TimeValue), null, "TimeValue", StormColumnFlags.CanSelect | StormColumnFlags.CanInsert | StormColumnFlags.CanUpdate, UnifiedDbType.Time, 0, 0, 0, SaveAs.Default, 0, false, null, null, typeof(System.TimeOnly), null),
+ new(nameof(SqlWhereTestEntity.TimeValueN), null, "TimeValueN", StormColumnFlags.CanSelect | StormColumnFlags.CanInsert | StormColumnFlags.CanUpdate, UnifiedDbType.Time, 0, 0, 0, SaveAs.Default, 0, true, null, null, typeof(System.TimeOnly), null)
};
///
diff --git a/Tests/TestModels/SqlWhereTestEntity.cs b/Tests/TestModels/SqlWhereTestEntity.cs
index 856ba12..9e64476 100644
--- a/Tests/TestModels/SqlWhereTestEntity.cs
+++ b/Tests/TestModels/SqlWhereTestEntity.cs
@@ -1,4 +1,5 @@
-using AltaSoft.Storm.Attributes;
+using System;
+using AltaSoft.Storm.Attributes;
using AltaSoft.Storm.TestModels.VeryBadNamespace;
namespace AltaSoft.Storm.TestModels;
@@ -32,5 +33,13 @@ public partial record SqlWhereTestEntity
public bool BoolValue { get; set; }
public bool? BoolValueN { get; set; }
+
+ public DateOnly DateValue { get; set; }
+
+ public DateOnly? DateValueN { get; set; }
+
+ public TimeOnly TimeValue { get; set; }
+
+ public TimeOnly? TimeValueN { get; set; }
}
diff --git a/Tests/TrackingListTests/AltaSoft.Storm.TrackingListTests.csproj b/Tests/TrackingListTests/AltaSoft.Storm.TrackingListTests.csproj
index 3e40239..3a1e242 100644
--- a/Tests/TrackingListTests/AltaSoft.Storm.TrackingListTests.csproj
+++ b/Tests/TrackingListTests/AltaSoft.Storm.TrackingListTests.csproj
@@ -19,9 +19,9 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/AltaSoft.Storm/Helpers/ODataWhereStatementGenerator.cs b/src/AltaSoft.Storm/Helpers/ODataWhereStatementGenerator.cs
index bae873b..6535c5d 100644
--- a/src/AltaSoft.Storm/Helpers/ODataWhereStatementGenerator.cs
+++ b/src/AltaSoft.Storm/Helpers/ODataWhereStatementGenerator.cs
@@ -183,6 +183,13 @@ public override QueryNode Visit(ConstantNode nodeIn)
}
else
{
+#if NET10_0_OR_GREATER
+ value = value switch
+ {
+ DateTimeOffset { DateTime: var dt } when dbType is UnifiedDbType.DateTime or UnifiedDbType.DateTime2 or UnifiedDbType.SmallDateTime => dt,
+ _ => value
+ };
+#else
value = value switch
{
//Microsoft.OData.Edm.Date
@@ -192,6 +199,7 @@ public override QueryNode Visit(ConstantNode nodeIn)
DateTimeOffset { DateTime: var dt } when dbType is UnifiedDbType.DateTime or UnifiedDbType.DateTime2 or UnifiedDbType.SmallDateTime => dt,
_ => value
};
+#endif
}
var paramName = ParamPrefix + _paramIndex++.ToString(CultureInfo.InvariantCulture);
diff --git a/src/AltaSoft.Storm/StormControllerBase.cs b/src/AltaSoft.Storm/StormControllerBase.cs
index 5fa2c10..3590921 100644
--- a/src/AltaSoft.Storm/StormControllerBase.cs
+++ b/src/AltaSoft.Storm/StormControllerBase.cs
@@ -251,6 +251,19 @@ private static void AppendTableHints(StormTableHints hints, StringBuilder sb)
sb.Append(')');
}
+ ///
+ /// Appends a TOP (n) clause to a StringBuilder, if is set.
+ ///
+ /// The number of rows to limit the statement to, or null for no limit.
+ /// The StringBuilder to which the clause will be appended.
+ private static void AppendTopClause(int? topRows, StringBuilder sb)
+ {
+ if (topRows is not { } rows)
+ return;
+
+ sb.Append("TOP (").Append(rows).Append(") ");
+ }
+
///
/// Returns the corresponding SQL hint string for the given StormTableHints enum value.
///
diff --git a/src/AltaSoft.Storm/StormControllerBase.delete.cs b/src/AltaSoft.Storm/StormControllerBase.delete.cs
index 6076997..843b3bc 100644
--- a/src/AltaSoft.Storm/StormControllerBase.delete.cs
+++ b/src/AltaSoft.Storm/StormControllerBase.delete.cs
@@ -77,7 +77,7 @@ internal void PrepareDelete(
{
var sb = StormManager.GetStringBuilderFromPool();
- GenerateDeleteSql(command, queryParameters, queryParameters.TableHints, sb);
+ GenerateDeleteSql(command, queryParameters, queryParameters.TableHints, queryParameters.TopRows, sb);
command.SetStormCommandBaseParameters(sb.ToStringAndReturnToPool(), queryParameters);
}
@@ -123,7 +123,7 @@ internal void PrepareDelete(
command.SetStormCommandBaseParameters(sb.ToStringAndReturnToPool(), queryParameters);
}
- private void GenerateDeleteSql(IVirtualStormDbCommand command, IKeyAndWhereExpression queryParameters, StormTableHints tableHints, StringBuilder sb) where T : IDataBindable
+ private void GenerateDeleteSql(IVirtualStormDbCommand command, IKeyAndWhereExpression queryParameters, StormTableHints tableHints, int? topRows, StringBuilder sb) where T : IDataBindable
{
var paramIndex = 1;
var (startIndex, len) = (-1, 0);
@@ -141,7 +141,9 @@ private void GenerateDeleteSql(IVirtualStormDbCommand command, IKeyAndWhereEx
}
sb.AppendLine("SET NOCOUNT OFF;");
- sb.Append("DELETE FROM ").Append(QuotedObjectFullName);
+ sb.Append("DELETE ");
+ AppendTopClause(topRows, sb);
+ sb.Append("FROM ").Append(QuotedObjectFullName);
AppendTableHints(tableHints, sb);
if (startIndex < 0)
diff --git a/src/AltaSoft.Storm/StormControllerBase.update.cs b/src/AltaSoft.Storm/StormControllerBase.update.cs
index bb0d2b1..59f0816 100644
--- a/src/AltaSoft.Storm/StormControllerBase.update.cs
+++ b/src/AltaSoft.Storm/StormControllerBase.update.cs
@@ -102,7 +102,9 @@ internal void PrepareUpdate(
var paramIndex = 1;
var sb = StormManager.GetStringBuilderFromPool();
- sb.Append("UPDATE ").Append(QuotedObjectFullName);
+ sb.Append("UPDATE ");
+ AppendTopClause(queryParameters.TopRows, sb);
+ sb.Append(QuotedObjectFullName);
AppendTableHints(queryParameters.TableHints, sb);
sb.AppendLine();
sb.Append("SET ");
diff --git a/src/SharedAssemblyInfo.props b/src/SharedAssemblyInfo.props
index 9907c84..dba2e50 100644
--- a/src/SharedAssemblyInfo.props
+++ b/src/SharedAssemblyInfo.props
@@ -7,7 +7,7 @@
Gregory Nikolaishvili, Teimuraz Nikolaishvili
ALTA Software llc.
Copyright © 2024-2026 ALTA Software llc.
- 3.4.3
+ 3.5.0