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

Add metadata for optimistic concurrency support in sprocs #28569

Merged
merged 8 commits into from
Aug 5, 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
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.



// ReSharper disable once CheckNamespace
namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;

Expand Down
3 changes: 1 addition & 2 deletions src/EFCore.Relational/Design/AnnotationCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ public class AnnotationCodeGenerator : IAnnotationCodeGenerator
RelationalAnnotationNames.InsertStoredProcedure,
RelationalAnnotationNames.UpdateStoredProcedure,
RelationalAnnotationNames.MappingFragments,
RelationalAnnotationNames.RelationalOverrides,
RelationalAnnotationNames.ParameterDirection
RelationalAnnotationNames.RelationalOverrides
};

#region MethodInfos
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Data;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

namespace Microsoft.EntityFrameworkCore.Design.Internal;
Expand Down Expand Up @@ -166,16 +167,16 @@ private void Create(
mainBuilder.AppendLine(");").DecrementIndent()
.AppendLine();

var parameterParameters = parameters with { TargetName = functionVariable };
parameters = parameters with { TargetName = functionVariable };
foreach (var parameter in function.Parameters)
{
Create(parameter, parameterParameters);
Create(parameter, parameters);
}

CreateAnnotations(
function,
Generate,
parameters with { TargetName = functionVariable });
parameters);

mainBuilder
.Append(functionsVariable).Append("[").Append(code.Literal(function.ModelName)).Append("] = ").Append(functionVariable)
Expand Down Expand Up @@ -481,36 +482,36 @@ public virtual void Generate(ITrigger trigger, CSharpRuntimeAnnotationCodeGenera
private void Create(IStoredProcedure storedProcedure, string sprocVariable, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
{
AddNamespace(typeof(RuntimeStoredProcedure), parameters.Namespaces);
AddNamespace(typeof(ParameterDirection), parameters.Namespaces);

var code = Dependencies.CSharpHelper;
var mainBuilder = parameters.MainBuilder;
mainBuilder
.Append("var ").Append(sprocVariable).AppendLine(" = new RuntimeStoredProcedure(").IncrementIndent()
.Append(parameters.TargetName).AppendLine(",")
.Append(code.Literal(storedProcedure.Name)).AppendLine(",")
.Append(code.Literal(storedProcedure.Schema)).AppendLine(",")
.Append(code.Literal(storedProcedure.AreRowsAffectedReturned)).AppendLine(",")
.Append(code.Literal(storedProcedure.AreTransactionsSuppressed))
.AppendLine(");")
.DecrementIndent()
.AppendLine();


parameters = parameters with { TargetName = sprocVariable };
foreach (var parameter in storedProcedure.Parameters)
{
mainBuilder.Append(sprocVariable).Append(".AddParameter(")
.Append(code.Literal(parameter))
.AppendLine(");");
Create(parameter, parameters);
}

foreach (var resultColumn in storedProcedure.ResultColumns)
{
mainBuilder.Append(sprocVariable).Append(".AddResultColumn(")
.Append(code.Literal(resultColumn))
.AppendLine(");");
Create(resultColumn, parameters);
}

CreateAnnotations(
storedProcedure,
Generate,
parameters with { TargetName = sprocVariable });
parameters);
}

/// <summary>
Expand All @@ -521,6 +522,64 @@ private void Create(IStoredProcedure storedProcedure, string sprocVariable, CSha
public virtual void Generate(IStoredProcedure storedProcedure, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
=> GenerateSimpleAnnotations(parameters);

private void Create(IStoredProcedureParameter parameter, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
{
var code = Dependencies.CSharpHelper;
var mainBuilder = parameters.MainBuilder;
var parameterVariable = code.Identifier(parameter.Name, parameters.ScopeVariables, capitalize: false);

mainBuilder
.Append("var ").Append(parameterVariable).Append(" = ")
.Append(parameters.TargetName).AppendLine(".AddParameter(").IncrementIndent()
.Append(code.Literal(parameter.Name)).Append(", ")
.Append(code.Literal(parameter.Direction)).Append(", ")
.Append(code.Literal(parameter.ForRowsAffected)).Append(", ")
.Append(code.Literal(parameter.PropertyName!)).Append(", ")
.Append(code.Literal(parameter.ForOriginalValue))
.AppendLine(");").DecrementIndent();

CreateAnnotations(
parameter,
Generate,
parameters with { TargetName = parameterVariable });
}

/// <summary>
/// Generates code to create the given annotations.
/// </summary>
/// <param name="storedProcedure">The stored procedure to which the annotations are applied.</param>
/// <param name="parameters">Additional parameters used during code generation.</param>
public virtual void Generate(IStoredProcedureParameter storedProcedure, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
=> GenerateSimpleAnnotations(parameters);

private void Create(IStoredProcedureResultColumn resultColumn, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
{
var code = Dependencies.CSharpHelper;
var mainBuilder = parameters.MainBuilder;
var resultColumnVariable = code.Identifier(resultColumn.Name, parameters.ScopeVariables, capitalize: false);

mainBuilder
.Append("var ").Append(resultColumnVariable).Append(" = ")
.Append(parameters.TargetName).AppendLine(".AddResultColumn(").IncrementIndent()
.Append(code.Literal(resultColumn.Name)).Append(", ")
.Append(code.Literal(resultColumn.ForRowsAffected)).Append(", ")
.Append(code.Literal(resultColumn.PropertyName!))
.AppendLine(");").DecrementIndent();

CreateAnnotations(
resultColumn,
Generate,
parameters with { TargetName = resultColumnVariable });
}

/// <summary>
/// Generates code to create the given annotations.
/// </summary>
/// <param name="storedProcedure">The stored procedure to which the annotations are applied.</param>
/// <param name="parameters">Additional parameters used during code generation.</param>
public virtual void Generate(IStoredProcedureResultColumn storedProcedure, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
=> GenerateSimpleAnnotations(parameters);

/// <summary>
/// Generates code to create the given annotations.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,54 +357,6 @@ public static bool CanSetIsFixedLength(
bool? fixedLength,
bool fromDataAnnotation = false)
=> propertyBuilder.CanSetAnnotation(RelationalAnnotationNames.IsFixedLength, fixedLength, fromDataAnnotation);

/// <summary>
/// Sets the direction of the stored procedure parameter.
/// </summary>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="direction">The direction.</param>
/// <param name="storeObject">The identifier of the stored procedure.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>
/// The same builder instance if the configuration was applied,
/// <see langword="null" /> otherwise.
/// </returns>
public static IConventionPropertyBuilder? HasDirection(
this IConventionPropertyBuilder propertyBuilder,
ParameterDirection direction,
in StoreObjectIdentifier storeObject,
bool fromDataAnnotation = false)
{
if (!propertyBuilder.CanSetDirection(direction, storeObject, fromDataAnnotation))
{
return null;
}

propertyBuilder.Metadata.SetDirection(direction, storeObject, fromDataAnnotation);
return propertyBuilder;
}

/// <summary>
/// Returns a value indicating whether the given direction can be configured on the corresponding stored procedure parameter.
/// </summary>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="direction">The direction.</param>
/// <param name="storeObject">The identifier of the stored procedure.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns><see langword="true" /> if the property can be mapped to the given column.</returns>
public static bool CanSetDirection(
this IConventionPropertyBuilder propertyBuilder,
ParameterDirection direction,
in StoreObjectIdentifier storeObject,
bool fromDataAnnotation = false)
{
var overrides = (IConventionRelationalPropertyOverrides?)RelationalPropertyOverrides.Find(
propertyBuilder.Metadata, storeObject);
return overrides == null
|| (fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention)
.Overrides(overrides.GetDirectionConfigurationSource())
|| overrides.Direction == direction;
}

/// <summary>
/// Configures the default value expression for the column that the property maps to when targeting a
Expand Down
48 changes: 0 additions & 48 deletions src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

// ReSharper disable once CheckNamespace
Expand Down Expand Up @@ -1170,53 +1169,6 @@ private static bool IsOptionalSharingDependent(

return optional ?? (entityType.BaseType != null && entityType.FindDiscriminatorProperty() != null);
}

/// <summary>
/// Gets the direction of the corresponding stored procedure parameter.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="storeObject">The identifier of the stored procedure containing the parameter.</param>
/// <returns>
/// The direction of the corresponding stored procedure parameter.
/// </returns>
public static System.Data.ParameterDirection GetDirection(this IReadOnlyProperty property, in StoreObjectIdentifier storeObject)
=> property.FindOverrides(storeObject)?.Direction ?? System.Data.ParameterDirection.Input;

/// <summary>
/// Sets the direction of the corresponding stored procedure parameter.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="direction">The direction to set.</param>
/// <param name="storeObject">The identifier of the stored procedure containing the parameter.</param>
public static void SetDirection(
this IMutableProperty property,
System.Data.ParameterDirection? direction,
in StoreObjectIdentifier storeObject)
=> property.GetOrCreateOverrides(storeObject).Direction = direction;

/// <summary>
/// Sets the direction of the corresponding stored procedure parameter.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="direction">The direction to set.</param>
/// <param name="storeObject">The identifier of the stored procedure containing the parameter.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>The configured value.</returns>
public static System.Data.ParameterDirection? SetDirection(
this IConventionProperty property,
System.Data.ParameterDirection? direction,
in StoreObjectIdentifier storeObject,
bool fromDataAnnotation = false)
=> property.GetOrCreateOverrides(storeObject, fromDataAnnotation).SetDirection(direction, fromDataAnnotation);

/// <summary>
/// Gets the <see cref="ConfigurationSource" /> for the stored procedure parameter direction.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="storeObject">The identifier of the stored procedure containing the parameter.</param>
/// <returns>The <see cref="ConfigurationSource" /> for the stored procedure parameter direction.</returns>
public static ConfigurationSource? GetDirectionConfigurationSource(this IConventionProperty property, in StoreObjectIdentifier storeObject)
=> property.FindOverrides(storeObject)?.GetDirectionConfigurationSource();

/// <summary>
/// Returns the comment for the column this property is mapped to.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ protected override void InitializeModel(IModel model, bool designTime, bool prev
}
else
{
RelationalModel.Add(model, RelationalDependencies.RelationalAnnotationProvider, designTime);
RelationalModel.Add(
model,
RelationalDependencies.RelationalAnnotationProvider,
(IRelationalTypeMappingSource)Dependencies.ModelDependencies.TypeMappingSource,
designTime);
}
}
}
Loading