Skip to content
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

Some docs/exception messages for bulk delete #28523

Merged
merged 2 commits into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,19 +236,43 @@ internal static readonly MethodInfo AsSplitQueryMethodInfo
#region BulkDelete

/// <summary>
/// TBD
/// Deletes all entity instances which match the LINQ query from the database.
/// </summary>
/// <remarks>
roji marked this conversation as resolved.
Show resolved Hide resolved
/// <para>
/// This operation executes immediately against the database, rather than being deferred until
/// <see cref="DbContext.SaveChanges()" /> is called. It also does not interact with the EF change tracker in any way:
/// entity instances which happen to be tracked when this operation is invoked aren't taken into account, and aren't updated
/// to reflect the changes.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-bulk-operations">Executing bulk operations with EF Core</see>
/// for more information and examples.
/// </para>
/// </remarks>
/// <param name="source">The source query.</param>
/// <returns> TBD </returns>
/// <returns>The total number of entity instances deleted from the database.</returns>
public static int BulkDelete<TSource>(this IQueryable<TSource> source)
=> source.Provider.Execute<int>(Expression.Call(BulkDeleteMethodInfo.MakeGenericMethod(typeof(TSource)), source.Expression));

/// <summary>
/// TBD
/// Asynchronously deletes all entity instances which match the LINQ query from the database.
/// </summary>
/// <remarks>
/// <para>
/// This operation executes immediately against the database, rather than being deferred until
/// <see cref="DbContext.SaveChanges()" /> is called. It also does not interact with the EF change tracker in any way:
/// entity instances which happen to be tracked when this operation is invoked aren't taken into account, and aren't updated
/// to reflect the changes.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-bulk-operations">Executing bulk operations with EF Core</see>
/// for more information and examples.
/// </para>
/// </remarks>
/// <param name="source">The source query.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns> TBD </returns>
/// <returns>The total number of entity instances deleted from the database.</returns>
public static Task<int> BulkDeleteAsync<TSource>(this IQueryable<TSource> source, CancellationToken cancellationToken = default)
=> source.Provider is IAsyncQueryProvider provider
? provider.ExecuteAsync<Task<int>>(
Expand Down
14 changes: 14 additions & 0 deletions src/EFCore.Relational/Properties/RelationalStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/EFCore.Relational/Properties/RelationalStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@
<data name="BadSequenceType" xml:space="preserve">
<value>Invalid type for sequence. Valid types are long (the default), int, short, byte and decimal.</value>
</data>
<data name="BulkOperationOnKeylessEntityTypeWithUnsupportedOperator" xml:space="preserve">
<value>The bulk operation cannot be performed on keyless entity type '{entityType}', since it contains an operator not natively supported by the database provider.</value>
</data>
<data name="BulkOperationWithUnsupportedOperatorInSqlGeneration" xml:space="preserve">
<value>The bulk operation contains a select expression feature that isn't supported in the query SQL generator, but has been declared as supported in RelationalQueryableMethodTranslatingExpressionVisitor.</value>
</data>
<data name="CannotChangeWhenOpen" xml:space="preserve">
<value>The instance of DbConnection is currently in use. The connection can only be changed when the existing connection is not being used.</value>
</data>
Expand Down
3 changes: 1 addition & 2 deletions src/EFCore.Relational/Query/QuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ protected override Expression VisitDelete(DeleteExpression deleteExpression)
}
else
{
// TODO: Exception message
throw new InvalidOperationException();
throw new InvalidOperationException(RelationalStrings.BulkOperationWithUnsupportedOperatorInSqlGeneration);
}

return deleteExpression;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ private sealed class SelectExpressionMutableVerifyingExpressionVisitor : Express
{
switch (expression)
{
case SelectExpression selectExpression
when selectExpression.IsMutable():
case SelectExpression selectExpression when selectExpression.IsMutable():
throw new InvalidDataException(selectExpression.Print());

case ShapedQueryExpression shapedQueryExpression:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1029,8 +1029,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
}
else
{
// TODO: Exception message
throw new InvalidOperationException("specific message about keyless");
throw new InvalidOperationException(
RelationalStrings.BulkOperationOnKeylessEntityTypeWithUnsupportedOperator(entityType.DisplayName()));
}
}
}
Expand All @@ -1042,6 +1042,16 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
/// <summary>
/// Validates if the current select expression can be used for bulk delete operation or it requires to be pushed into a subquery.
/// </summary>
/// <remarks>
/// <para>
/// By default, only single-table select expressions are supported, and only with a predicate.
/// </para>
/// <para>
/// Providers can override this to allow more select expression features to be supported without pushing down into a subquery.
/// When doing this, VisitDelete must also be overridden in the provider's QuerySqlGenerator to add SQL generation support for
/// the feature.
/// </para>
/// </remarks>
/// <param name="selectExpression">The select expression to validate.</param>
/// <param name="entityShaperExpression">The entity shaper expression on which delete operation is being applied.</param>
/// <param name="tableExpression">The table expression from which rows are being deleted.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ protected override Expression VisitExtension(Expression extensionExpression)
: base.VisitExtension(extensionExpression);

/// <summary>
/// asdagv
/// Visits the given <paramref name="nonQueryExpression" />, returning an expression that when compiled, can execute the non-
/// query operation against the database.
/// </summary>
/// <param name="nonQueryExpression">asdasfdsa</param>
/// <returns>asdasd</returns>
/// <param name="nonQueryExpression">The expression to be compiled.</param>
/// <returns>An expression which executes a non-query operation.</returns>
protected virtual Expression VisitNonQuery(NonQueryExpression nonQueryExpression)
{
var relationalCommandCache = new RelationalCommandCache(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ protected override Expression VisitDelete(DeleteExpression deleteExpression)
}
else
{
throw new NotSupportedException();
throw new InvalidOperationException(RelationalStrings.BulkOperationWithUnsupportedOperatorInSqlGeneration);
}

return deleteExpression;
Expand Down