diff --git a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs
index 56be96e3841..5f90c7dfccc 100644
--- a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs
+++ b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs
@@ -496,9 +496,7 @@ public virtual DbParameter CreateParameter(
parameter.Direction = direction;
parameter.ParameterName = name;
- var isInputParameter = direction is ParameterDirection.Input or ParameterDirection.InputOutput;
-
- if (isInputParameter)
+ if (direction.HasFlag(ParameterDirection.Input))
{
value = NormalizeEnumValue(value);
@@ -512,7 +510,10 @@ public virtual DbParameter CreateParameter(
if (nullable.HasValue)
{
- Check.DebugAssert(nullable.Value || !isInputParameter || value != null, "Null value in a non-nullable input parameter");
+ Check.DebugAssert(nullable.Value
+ || !direction.HasFlag(ParameterDirection.Input)
+ || value != null,
+ "Null value in a non-nullable input parameter");
parameter.IsNullable = nullable.Value;
}
diff --git a/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs b/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs
index 93b6d983247..2469f04356a 100644
--- a/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs
+++ b/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs
@@ -97,7 +97,7 @@ void HandleOutputParameters()
{
if (requiresResultPropagation)
{
- command.PropagateOutputParameters(reader);
+ command.PropagateOutputParameters(reader.DbCommand.Parameters);
}
// TODO: Rows affected via output parameter
@@ -164,10 +164,9 @@ protected override async Task ConsumeAsync(
// TODO: Maybe record if there's any sprocs in the batch, and if not, skip this
while (true)
{
- if (command.StoredProcedure is not null)
+ if (resultSetMapping.HasFlag(ResultSetMapping.HasOutputParameters))
{
- command.PropagateOutputParameters(reader);
- // TODO: Rows affected via output parameter
+ HandleOutputParameters();
}
if (commandIndex == lastHandledCommandIndex)
@@ -175,15 +174,22 @@ protected override async Task ConsumeAsync(
break;
}
- command = ModificationCommands[++commandIndex];
+ resultSetMapping = CommandResultSet[++commandIndex];
+ command = ModificationCommands[commandIndex];
+ requiresResultPropagation = command.RequiresResultPropagation;
}
}
else if (resultSetMapping.HasFlag(ResultSetMapping.HasOutputParameters))
{
// Handle output parameters for commands which have no result rows. Commands with result rows are handled above.
+ HandleOutputParameters();
+ }
+
+ void HandleOutputParameters()
+ {
if (requiresResultPropagation)
{
- command.PropagateOutputParameters(reader);
+ command.PropagateOutputParameters(reader.DbCommand.Parameters);
}
// TODO: Rows affected via output parameter
diff --git a/src/EFCore.Relational/Update/IReadOnlyModificationCommand.cs b/src/EFCore.Relational/Update/IReadOnlyModificationCommand.cs
index 09bdcfd16b4..aac721e5a2f 100644
--- a/src/EFCore.Relational/Update/IReadOnlyModificationCommand.cs
+++ b/src/EFCore.Relational/Update/IReadOnlyModificationCommand.cs
@@ -69,9 +69,9 @@ public interface IReadOnlyModificationCommand
public void PropagateResults(RelationalDataReader relationalReader);
///
- /// Reads output parameters returned from the database in the given and propagates them back to
- /// into the appropriate from which the values can be propagated on to tracked entities.
+ /// Reads output parameters returned from the database in the given and propagates them back
+ /// to into the appropriate from which the values can be propagated on to tracked entities.
///
- /// The relational reader containing the values read from the database.
- public void PropagateOutputParameters(RelationalDataReader relationalReader);
+ /// The parameter collection from which to propagate output values.
+ public void PropagateOutputParameters(DbParameterCollection parameterCollection);
}
diff --git a/src/EFCore.Relational/Update/ModificationCommand.cs b/src/EFCore.Relational/Update/ModificationCommand.cs
index 11eee3f58d5..bc5f773be16 100644
--- a/src/EFCore.Relational/Update/ModificationCommand.cs
+++ b/src/EFCore.Relational/Update/ModificationCommand.cs
@@ -500,7 +500,7 @@ public virtual void PropagateResults(RelationalDataReader relationalReader)
}
///
- public virtual void PropagateOutputParameters(RelationalDataReader relationalReader)
+ public virtual void PropagateOutputParameters(DbParameterCollection parameterCollection)
{
// Note that this call sets the value into a sidecar and will only commit to the actual entity
// if SaveChanges is successful.
@@ -528,7 +528,7 @@ public virtual void PropagateOutputParameters(RelationalDataReader relationalRea
// Another option is to put the invariant name in the DbParameterCollection (without the prefix); the prefix isn't needed
// there AFAIK (but should check this is OK across databases.
var prefixedName = "@" + columnModification.ParameterName;
- var dbParameter = relationalReader.DbCommand.Parameters[prefixedName];
+ var dbParameter = parameterCollection[prefixedName];
columnModification.Value = dbParameter.Value;
}
}
diff --git a/src/EFCore.Sqlite.Core/Infrastructure/Internal/SqliteModelValidator.cs b/src/EFCore.Sqlite.Core/Infrastructure/Internal/SqliteModelValidator.cs
index 8185e670f57..5152b25318c 100644
--- a/src/EFCore.Sqlite.Core/Infrastructure/Internal/SqliteModelValidator.cs
+++ b/src/EFCore.Sqlite.Core/Infrastructure/Internal/SqliteModelValidator.cs
@@ -85,11 +85,10 @@ protected virtual void ValidateNoStoredProcedures(
{
foreach (var entityType in model.GetEntityTypes())
{
- if (entityType.GetInsertStoredProcedureMappings().Any()
- || entityType.GetUpdateStoredProcedureMappings().Any()
- || entityType.GetDeleteStoredProcedureMappings().Any())
+ if (entityType.GetInsertStoredProcedure() is not null
+ || entityType.GetUpdateStoredProcedure() is not null
+ || entityType.GetDeleteStoredProcedure() is not null)
{
- // TODO: Make this throw and not warn (like other validations) since updates won't work
throw new InvalidOperationException(SqliteStrings.StoredProceduresNotSupported(entityType.DisplayName()));
}
}