Skip to content

Commit

Permalink
Add metadata for optimistic concurrency support in sprocs
Browse files Browse the repository at this point in the history
Add more information to the relational model for sproc mapping
Remove EFCore.Design dependency from EFCore.Specification.Tests

Part of #28435
  • Loading branch information
AndriySvyryd authored Aug 5, 2022
1 parent badf293 commit d724497
Show file tree
Hide file tree
Showing 124 changed files with 5,140 additions and 926 deletions.
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

0 comments on commit d724497

Please sign in to comment.