-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CancellationToken support to QueryAsync overload #2138
base: main
Are you sure you want to change the base?
Add CancellationToken support to QueryAsync overload #2138
Conversation
This change introduces a CancellationToken parameter to the QueryAsync method, enabling support for cooperative cancellation of asynchronous database queries. The modification ensures better resilience and control over long-running or potentially cancelable operations. This fixes issues DapperLib#2125 and DapperLib#1938.
This would be a breaking change. I don't think this can me added until a new major release of Dapper |
Hi, I'm a bit unsure why this would be considered a breaking change as the new CancellationToken parameter is optional when calling the QueryAsync method. That said I'm new to this code base, perhaps I'm missing something? However, if this is really a breaking change, then I agree that it would make most sense to wait with merging this until the next major release. |
This is in detail, and most C# developers accept this change as it is not breaking in a common way. But there is edge cases adding an optionnal parameter is a breaking change. For example: Here is startup case public class Foo
{
public static async Task Bar()
{
await Task.Delay(5);
System.Console.WriteLine("Bar");
}
}
public class MyProgram()
{
public static async Task MyMain()
{
Func<Task> MyFunc = Foo.Bar;
await MyFunc();
}
} When modifying to Here is the change without breaking change: public class Foo
{
public static Task Bar()
{
return Bar(default);
}
public static async Task Bar(CancellationToken cts)
{
await Task.Delay(5, cts);
System.Console.WriteLine("Bar");
}
}
public class MyProgram()
{
public static async Task MyMain()
{
Func<Task> MyFunc = Foo.Bar;
await MyFunc();
}
} This is not breaking anymore. |
To be clear: any change to the parameters is always a breaking change. Fundamentally, there are two very different kinds of "break" we need to consider:
Changes can be either or both (or neither) kind of break. So: we don't want that. Adding a parameter - even an optional parameter - is a binary breaking: existing code compiled against the old method will simply stop working if the library is updated in this way, unless all code using it is recompiled. The compiled IL indicates a very specific method - one that will no longer be found (optional parameters don't make any difference for IL bind purposes). It is not always (or even often) the case that every package is rebuilt for every deployment - and often, there may be intermediate 3rd-party wrapper packages in the mix, meaning that it isn't even possible to simply rebuild it - you need to petition the 3rd party (who might be busy or otherwise unavailable) to update and redeploy their package - and there might even be multiple chained 3rd parties that need to update in the right order! So, yeah. We cannot and will not just add optional parameters: instead, we need to add a new overload with the additional parameter. Note, however, that where appropriate it is possible to retire old overloads by simply removing the "this" modifier; this is not a binary break, and is not a source break as long as the remaining overloads over the existing and new use-cases. Most of the time, however, both the old and new overloads retain the "this".
I hope the above explains why this is a breaking change as written.
Nothing in the above is specific to this codebase - it is fundamentally how library packages work. This is less of a problem if the only people who consume a library are in the same team, and everything will always get updated together: but if you're a public library, this is not the case.
Even at majors, we don't wilfully make breaking changes without a very good reason. In this case, the change can be applied by adding overloads rather than parameters. |
This change introduces an optional CancellationToken parameter to the QueryAsync method, enabling support for cancellation of asynchronous database queries. The modification ensures better resilience and control over long-running or potentially cancelable operations.
This fixes issues #2125 and #1938.