Skip to content

Fspes 140#76

Open
MatteoDelOmbra wants to merge 3 commits into
mainfrom
fspes-140
Open

Fspes 140#76
MatteoDelOmbra wants to merge 3 commits into
mainfrom
fspes-140

Conversation

@MatteoDelOmbra

@MatteoDelOmbra MatteoDelOmbra commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Checklist

  • Task version updated (x.x.0)
  • CHANGELOG.md updated
  • Solution builds
  • Warnings resolved (if possible)
  • Typos resolved
  • Tests cover new code
  • Description how to run tests locally added to README.md (if needed)
  • All tests pass locally

Summary by CodeRabbit

  • Changed

    • Result.Count now reports the total number of rows on successful execution and an estimated number of rows copied before failure on errors.
  • Documentation

    • Updated documentation for Result.Count and NotifyAfter configuration to reflect new behavior.
  • Chores

    • Version updated to 3.3.0.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@MatteoDelOmbra, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 54 minutes and 8 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 20d1024d-5b96-46f2-8dce-5f8099928d85

📥 Commits

Reviewing files that changed from the base of the PR and between dbba961 and fbd73bc.

📒 Files selected for processing (1)
  • Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert/BulkInsert.cs

Walkthrough

BulkInsert now reports the actual total row count in Result.Count on success (using totalRows instead of the event-driven counter) and an estimated rows-copied value on failure (by attaching Data["RowsCopied"] to thrown exceptions and reading it in all catch paths). NotifyAfter calculation was refactored to a switch expression. XML docs, tests, changelog, and version were updated to match.

Changes

Result.Count Reporting Overhaul

Layer / File(s) Summary
Result.Count and NotifyAfter contract docs
Frends.MicrosoftSQL.BulkInsert/Definitions/Result.cs, Frends.MicrosoftSQL.BulkInsert/Definitions/Options.cs
XML doc for Result.Count updated to describe the approximation-on-failure behavior via Options.NotifyAfter; NotifyAfter doc revised to reflect new above-row-count semantics.
ExecuteHandler: totalRows, NotifyAfter switch, and RowsCopied on failure
Frends.MicrosoftSQL.BulkInsert/BulkInsert.cs
ExecuteHandler computes totalRows upfront, switches to a switch expression for NotifyAfter, returns totalRows on success, and on WriteToServerAsync failure attaches Data["RowsCopied"] plus a computed row-range message to the thrown exception.
BulkInsert catch paths threading RowsCopied into Result
Frends.MicrosoftSQL.BulkInsert/BulkInsert.cs
Non-transactional catch reads RowsCopied from ex.Data and returns Result(false, rowsCopied) instead of 0; transactional rollback and outer catch similarly extract RowsCopied from exception Data when ThrowErrorOnFailure is false.
Tests, changelog, and version bump
Frends.MicrosoftSQL.BulkInsert.Tests/UnitTests.cs, CHANGELOG.md, Frends.MicrosoftSQL.BulkInsert.csproj
NotifyAfter test assertions updated from result.Count == 0 to result.Count == 3; changelog documents the 3.3.0 behavior change; package version bumped to 3.3.0.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • FrendsPlatform/Frends.MicrosoftSQL#56: Modifies ExecuteHandler's NotifyAfter and row-notification logic and updates Options.NotifyAfter documentation and tests — directly related to the same code paths changed here.
  • FrendsPlatform/Frends.MicrosoftSQL#75: Touches Result.Count documentation and CHANGELOG.md/version bump for BulkInsert, which this PR supersedes with matching behavioral changes.

Suggested reviewers

  • RikuVirtanen
  • ttossavainen

Poem

🐇 Hop hop, the rows are tallied right,
No more returning zero on a flight!
When errors strike mid-copy spree,
RowsCopied tells you where we'd be.
The changelog blooms, version shines at three —
A bunny loves when counts run free! 🌸

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Fspes 140' is vague and uses a non-descriptive ticket reference that does not convey meaningful information about the changeset to someone reviewing the PR history. Revise the title to clearly describe the main change, such as 'Update Result.Count to report actual rows on success and estimated rows on failure' or 'Improve BulkInsert count reporting behavior'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fspes-140

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert.Tests/UnitTests.cs (1)

333-336: 🏗️ Heavy lift

Add failure-path assertions for the new Result.Count contract.

These updates validate success results, but the PR’s key change also includes failure-time estimated counts (RowsCopied). Please add tests where ThrowErrorOnFailure = false and WriteToServerAsync fails after partial progress, then assert result.Count reflects the expected approximation.

As per coding guidelines, "Confirm unit tests exist and provide at least 80% coverage."

Also applies to: 372-375

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert.Tests/UnitTests.cs`
around lines 333 - 336, The current test only validates the success path for the
result.Count property, but the PR introduces new behavior where result.Count
should reflect estimated row counts even on failure when ThrowErrorOnFailure is
false. Add additional test cases that configure options with ThrowErrorOnFailure
set to false, simulate a failure scenario in WriteToServerAsync after partial
data has been copied, and then assert that result.Count accurately reflects the
expected approximate number of rows that were successfully copied before the
failure occurred.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert/BulkInsert.cs`:
- Around line 189-196: The SetEmptyDataRowsToNull method uses
Array.IndexOf(row.ItemArray, column) inside value iteration, which always
returns the index of the first matching empty value in the row, causing
duplicate empty strings to update only the first occurrence. Replace the
value-based foreach loop with index-based iteration using a for loop that
iterates through the column indices directly, so you can access and update each
column by its actual position without relying on Array.IndexOf which may resolve
to the wrong column when values repeat.

In
`@Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert/Definitions/Options.cs`:
- Around line 22-23: The XML documentation comment for the NotifyAfter property
contains a duplicated and grammatically incorrect second sentence. Remove the
second documentation line that starts with "Notified value is useful for error
handling" as it repeats the same concept as the first line and contains a typo
("occured" instead of "occurred"). Keep only the first sentence which clearly
explains the purpose of NotifyAfter for error handling.

---

Nitpick comments:
In
`@Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert.Tests/UnitTests.cs`:
- Around line 333-336: The current test only validates the success path for the
result.Count property, but the PR introduces new behavior where result.Count
should reflect estimated row counts even on failure when ThrowErrorOnFailure is
false. Add additional test cases that configure options with ThrowErrorOnFailure
set to false, simulate a failure scenario in WriteToServerAsync after partial
data has been copied, and then assert that result.Count accurately reflects the
expected approximate number of rows that were successfully copied before the
failure occurred.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3ff50afc-8775-44d7-b39f-276f5be8e906

📥 Commits

Reviewing files that changed from the base of the PR and between ffb3380 and dbba961.

📒 Files selected for processing (6)
  • Frends.MicrosoftSQL.BulkInsert/CHANGELOG.md
  • Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert.Tests/UnitTests.cs
  • Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert/BulkInsert.cs
  • Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert/Definitions/Options.cs
  • Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert/Definitions/Result.cs
  • Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert.csproj

Comment on lines 189 to +196
foreach (var table in dataSet.Tables.Cast<DataTable>())
foreach (var row in table.Rows.Cast<DataRow>())
foreach (var column in row.ItemArray)
if (column.ToString() == string.Empty)
{
var index = Array.IndexOf(row.ItemArray, column);
row[index] = null;
}
foreach (var row in table.Rows.Cast<DataRow>())
foreach (var column in row.ItemArray)
if (column.ToString() == string.Empty)
{
var index = Array.IndexOf(row.ItemArray, column);
row[index] = null;
}

@coderabbitai coderabbitai Bot Jun 18, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

SetEmptyDataRowsToNull can write to the wrong column when values repeat.

Using Array.IndexOf(row.ItemArray, column) inside value iteration resolves the first matching index, so duplicate empty values in the same row can leave later columns unchanged.

Suggested fix (index-based iteration)
 private static void SetEmptyDataRowsToNull(DataSet dataSet)
 {
     foreach (var table in dataSet.Tables.Cast<DataTable>())
     foreach (var row in table.Rows.Cast<DataRow>())
-    foreach (var column in row.ItemArray)
-        if (column.ToString() == string.Empty)
-        {
-            var index = Array.IndexOf(row.ItemArray, column);
-            row[index] = null;
-        }
+    {
+        for (var i = 0; i < row.ItemArray.Length; i++)
+        {
+            if (row[i] is string value && value.Length == 0)
+                row[i] = DBNull.Value;
+        }
+    }
 }
🧰 Tools
🪛 GitHub Actions: BulkInsert build test / 0_build _ Build on ubuntu-22.04.txt

[error] 190-190: dotnet format reported WHITESPACE issues. Fix whitespace formatting by inserting '\s\s\s\s'.


[error] 191-191: dotnet format reported WHITESPACE issues. Fix whitespace formatting by inserting '\s\s\s\s\s\s\s\s'.


[error] 192-192: dotnet format reported WHITESPACE issues. Fix whitespace formatting by inserting '\s\s\s\s\s\s\s\s'.


[error] 193-193: dotnet format reported WHITESPACE issues. Fix whitespace formatting by inserting '\s\s\s\s\s\s\s\s'.


[error] 194-194: dotnet format reported WHITESPACE issues. Fix whitespace formatting by inserting '\s\s\s\s\s\s\s\s'.


[error] 195-195: dotnet format reported WHITESPACE issues. Fix whitespace formatting by inserting '\s\s\s\s\s\s\s\s'.


[error] 196-196: dotnet format reported WHITESPACE issues. Fix whitespace formatting by inserting '\s\s\s\s\s\s\s\s'.

🪛 GitHub Actions: BulkInsert build test / build _ Build on ubuntu-22.04

[error] 190-190: dotnet format (WHITESPACE) failed. Fix whitespace formatting. Insert '\s\s\s\s'.


[error] 191-191: dotnet format (WHITESPACE) failed. Fix whitespace formatting. Insert '\s\s\s\s\s\s\s\s'.


[error] 192-192: dotnet format (WHITESPACE) failed. Fix whitespace formatting. Insert '\s\s\s\s\s\s\s\s'.


[error] 193-193: dotnet format (WHITESPACE) failed. Fix whitespace formatting. Insert '\s\s\s\s\s\s\s\s'.


[error] 194-194: dotnet format (WHITESPACE) failed. Fix whitespace formatting. Insert '\s\s\s\s\s\s\s\s'.


[error] 195-195: dotnet format (WHITESPACE) failed. Fix whitespace formatting. Insert '\s\s\s\s\s\s\s\s'.


[error] 196-196: dotnet format (WHITESPACE) failed. Fix whitespace formatting. Insert '\s\s\s\s\s\s\s\s'.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert/BulkInsert.cs`
around lines 189 - 196, The SetEmptyDataRowsToNull method uses
Array.IndexOf(row.ItemArray, column) inside value iteration, which always
returns the index of the first matching empty value in the row, causing
duplicate empty strings to update only the first occurrence. Replace the
value-based foreach loop with index-based iteration using a for loop that
iterates through the column indices directly, so you can access and update each
column by its actual position without relying on Array.IndexOf which may resolve
to the wrong column when values repeat.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MatteoDelOmbra This one is not related to your fix, but worth checking

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines 22 to +23
/// Notification events can be used for error handling to see approximately which row the error occurred at.
/// Notified value is useful for error handling and show approximately which row the error occured at

@coderabbitai coderabbitai Bot Jun 18, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix duplicated/typoed NotifyAfter XML doc sentence.

The second sentence repeats the same idea and contains a typo (occured).

Suggested doc cleanup
-    /// Notification events can be used for error handling to see approximately which row the error occurred at.
-    /// Notified value is useful for error handling and show approximately which row the error occured at
+    /// Notification events can be used for error handling to show approximately which row the error occurred at.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Notification events can be used for error handling to see approximately which row the error occurred at.
/// Notified value is useful for error handling and show approximately which row the error occured at
/// Notification events can be used for error handling to show approximately which row the error occurred at.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Frends.MicrosoftSQL.BulkInsert/Frends.MicrosoftSQL.BulkInsert/Definitions/Options.cs`
around lines 22 - 23, The XML documentation comment for the NotifyAfter property
contains a duplicated and grammatically incorrect second sentence. Remove the
second documentation line that starts with "Notified value is useful for error
handling" as it repeats the same concept as the first line and contains a typo
("occured" instead of "occurred"). Keep only the first sentence which clearly
explains the purpose of NotifyAfter for error handling.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MatteoDelOmbra check suggested fix from coderabbit

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines 22 to +23
/// Notification events can be used for error handling to see approximately which row the error occurred at.
/// Notified value is useful for error handling and show approximately which row the error occured at

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MatteoDelOmbra check suggested fix from coderabbit

Comment on lines 189 to +196
foreach (var table in dataSet.Tables.Cast<DataTable>())
foreach (var row in table.Rows.Cast<DataRow>())
foreach (var column in row.ItemArray)
if (column.ToString() == string.Empty)
{
var index = Array.IndexOf(row.ItemArray, column);
row[index] = null;
}
foreach (var row in table.Rows.Cast<DataRow>())
foreach (var column in row.ItemArray)
if (column.ToString() == string.Empty)
{
var index = Array.IndexOf(row.ItemArray, column);
row[index] = null;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MatteoDelOmbra This one is not related to your fix, but worth checking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants