Skip to content

Commit

Permalink
Sync EF Core to 7.0.0-preview.7.22359.1
Browse files Browse the repository at this point in the history
And use Npgsql 7.0.0-preview.6, dotnet SDK 7.0.0-preview.6

Closes npgsql#2433
  • Loading branch information
roji committed Jul 21, 2022
1 parent 8954553 commit 9903e84
Show file tree
Hide file tree
Showing 17 changed files with 338 additions and 114 deletions.
6 changes: 3 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project>
<PropertyGroup>
<EFCoreVersion>7.0.0-preview.7.22359.1</EFCoreVersion>
<MicrosoftExtensionsVersion>7.0.0-preview.6.22354.1</MicrosoftExtensionsVersion>
<NpgsqlVersion>7.0.0-preview.6-ci.20220710T074055</NpgsqlVersion>
<EFCoreVersion>7.0.0-preview.7.22365.1</EFCoreVersion>
<MicrosoftExtensionsVersion>7.0.0-preview.7.22364.6</MicrosoftExtensionsVersion>
<NpgsqlVersion>7.0.0-preview.6</NpgsqlVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "7.0.100-preview.4.22252.9",
"version": "7.0.100-preview.6.22352.1",
"rollForward": "latestMajor",
"allowPrerelease": "true"
}
Expand Down
165 changes: 145 additions & 20 deletions src/EFCore.PG/Extensions/MetadataExtensions/NpgsqlPropertyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,38 +259,79 @@ internal static NpgsqlValueGenerationStrategy GetValueGenerationStrategy(
in StoreObjectIdentifier storeObject,
ITypeMappingSource? typeMappingSource)
{
if (property[NpgsqlAnnotationNames.ValueGenerationStrategy] is { } annotation)
var @override = property.FindOverrides(storeObject)?.FindAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy);
if (@override != null)
{
return (NpgsqlValueGenerationStrategy)annotation;
return (NpgsqlValueGenerationStrategy?)@override.Value ?? NpgsqlValueGenerationStrategy.None;
}

if (property.FindSharedStoreObjectRootProperty(storeObject) is { } sharedTableRootProperty)
var annotation = property.FindAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy);
if (annotation?.Value != null
&& StoreObjectIdentifier.Create(property.DeclaringEntityType, storeObject.StoreObjectType) == storeObject)
{
return (NpgsqlValueGenerationStrategy)annotation.Value;
}

var table = storeObject;
var sharedTableRootProperty = property.FindSharedStoreObjectRootProperty(storeObject);
if (sharedTableRootProperty != null)
{
return sharedTableRootProperty.GetValueGenerationStrategy(storeObject) is var valueGenerationStrategy &&
valueGenerationStrategy switch
{
NpgsqlValueGenerationStrategy.IdentityByDefaultColumn => true,
NpgsqlValueGenerationStrategy.IdentityAlwaysColumn => true,
NpgsqlValueGenerationStrategy.SerialColumn => true,
_ => false
}
&& !property.GetContainingForeignKeys().Any(fk => !fk.IsBaseLinking())
? valueGenerationStrategy
return sharedTableRootProperty.GetValueGenerationStrategy(storeObject, typeMappingSource) is var npgsqlValueGenerationStrategy
&& npgsqlValueGenerationStrategy is
NpgsqlValueGenerationStrategy.IdentityByDefaultColumn
or NpgsqlValueGenerationStrategy.IdentityAlwaysColumn
or NpgsqlValueGenerationStrategy.SerialColumn
&& table.StoreObjectType == StoreObjectType.Table
&& !property.GetContainingForeignKeys().Any(
fk =>
!fk.IsBaseLinking()
|| (StoreObjectIdentifier.Create(fk.PrincipalEntityType, StoreObjectType.Table)
is StoreObjectIdentifier principal
&& fk.GetConstraintName(table, principal) != null))
? npgsqlValueGenerationStrategy
: NpgsqlValueGenerationStrategy.None;
}

if (property.ValueGenerated != ValueGenerated.OnAdd
|| property.GetContainingForeignKeys().Any(fk => !fk.IsBaseLinking())
|| table.StoreObjectType != StoreObjectType.Table
|| property.TryGetDefaultValue(storeObject, out _)
|| property.GetDefaultValueSql() is not null
|| property.GetComputedColumnSql() is not null)
|| property.GetDefaultValueSql(storeObject) != null
|| property.GetComputedColumnSql(storeObject) != null
|| property.GetContainingForeignKeys()
.Any(fk =>
!fk.IsBaseLinking()
|| (StoreObjectIdentifier.Create(fk.PrincipalEntityType, StoreObjectType.Table)
is StoreObjectIdentifier principal
&& fk.GetConstraintName(table, principal) != null)))
{
return NpgsqlValueGenerationStrategy.None;
}

return GetDefaultValueGenerationStrategy(property, storeObject, typeMappingSource);
var defaultStrategy = GetDefaultValueGenerationStrategy(property, storeObject, typeMappingSource);
if (defaultStrategy != NpgsqlValueGenerationStrategy.None)
{
if (annotation != null)
{
return (NpgsqlValueGenerationStrategy?)annotation.Value ?? NpgsqlValueGenerationStrategy.None;
}
}

return defaultStrategy;
}

/// <summary>
/// Returns the <see cref="NpgsqlValueGenerationStrategy" /> to use for the property.
/// </summary>
/// <remarks>
/// If no strategy is set for the property, then the strategy to use will be taken from the <see cref="IModel" />.
/// </remarks>
/// <param name="overrides">The property overrides.</param>
/// <returns>The strategy, or <see cref="NpgsqlValueGenerationStrategy.None" /> if none was set.</returns>
public static NpgsqlValueGenerationStrategy? GetValueGenerationStrategy(
this IReadOnlyRelationalPropertyOverrides overrides)
=> (NpgsqlValueGenerationStrategy?)overrides.FindAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy)
?.Value;

private static NpgsqlValueGenerationStrategy GetDefaultValueGenerationStrategy(IReadOnlyProperty property)
{
var modelStrategy = property.DeclaringEntityType.Model.GetValueGenerationStrategy();
Expand Down Expand Up @@ -356,13 +397,77 @@ public static void SetValueGenerationStrategy(
/// <param name="value">The strategy to use.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
public static NpgsqlValueGenerationStrategy? SetValueGenerationStrategy(
this IConventionProperty property, NpgsqlValueGenerationStrategy? value, bool fromDataAnnotation = false)
this IConventionProperty property,
NpgsqlValueGenerationStrategy? value,
bool fromDataAnnotation = false)
{
CheckValueGenerationStrategy(property, value);

property.SetOrRemoveAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation);
return (NpgsqlValueGenerationStrategy?)property.SetOrRemoveAnnotation(
NpgsqlAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation)
?.Value;
}

/// <summary>
/// Sets the <see cref="NpgsqlValueGenerationStrategy" /> to use for the property for a particular table.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="value">The strategy to use.</param>
/// <param name="storeObject">The identifier of the table containing the column.</param>
public static void SetValueGenerationStrategy(
this IMutableProperty property,
NpgsqlValueGenerationStrategy? value,
in StoreObjectIdentifier storeObject)
=> property.GetOrCreateOverrides(storeObject)
.SetValueGenerationStrategy(value);

/// <summary>
/// Sets the <see cref="NpgsqlValueGenerationStrategy" /> to use for the property for a particular table.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="value">The strategy to use.</param>
/// <param name="storeObject">The identifier of the table containing the column.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>The configured value.</returns>
public static NpgsqlValueGenerationStrategy? SetValueGenerationStrategy(
this IConventionProperty property,
NpgsqlValueGenerationStrategy? value,
in StoreObjectIdentifier storeObject,
bool fromDataAnnotation = false)
=> property.GetOrCreateOverrides(storeObject, fromDataAnnotation)
.SetValueGenerationStrategy(value, fromDataAnnotation);

/// <summary>
/// Sets the <see cref="NpgsqlValueGenerationStrategy" /> to use for the property for a particular table.
/// </summary>
/// <param name="overrides">The property overrides.</param>
/// <param name="value">The strategy to use.</param>
public static void SetValueGenerationStrategy(
this IMutableRelationalPropertyOverrides overrides,
NpgsqlValueGenerationStrategy? value)
{
CheckValueGenerationStrategy(overrides.Property, value);

overrides.SetOrRemoveAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy, value);
}

/// <summary>
/// Sets the <see cref="NpgsqlValueGenerationStrategy" /> to use for the property for a particular table.
/// </summary>
/// <param name="overrides">The property overrides.</param>
/// <param name="value">The strategy to use.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>The configured value.</returns>
public static NpgsqlValueGenerationStrategy? SetValueGenerationStrategy(
this IConventionRelationalPropertyOverrides overrides,
NpgsqlValueGenerationStrategy? value,
bool fromDataAnnotation = false)
{
CheckValueGenerationStrategy(overrides.Property, value);

return value;
return (NpgsqlValueGenerationStrategy?)overrides.SetOrRemoveAnnotation(
NpgsqlAnnotationNames.ValueGenerationStrategy, value, fromDataAnnotation)
?.Value;
}

private static void CheckValueGenerationStrategy(IReadOnlyProperty property, NpgsqlValueGenerationStrategy? value)
Expand Down Expand Up @@ -398,6 +503,26 @@ private static void CheckValueGenerationStrategy(IReadOnlyProperty property, Npg
this IConventionProperty property)
=> property.FindAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy)?.GetConfigurationSource();

/// <summary>
/// Returns the <see cref="ConfigurationSource" /> for the <see cref="NpgsqlValueGenerationStrategy" /> for a particular table.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="storeObject">The identifier of the table containing the column.</param>
/// <returns>The <see cref="ConfigurationSource" /> for the <see cref="NpgsqlValueGenerationStrategy" />.</returns>
public static ConfigurationSource? GetValueGenerationStrategyConfigurationSource(
this IConventionProperty property,
in StoreObjectIdentifier storeObject)
=> property.FindOverrides(storeObject)?.GetValueGenerationStrategyConfigurationSource();

/// <summary>
/// Returns the <see cref="ConfigurationSource" /> for the <see cref="NpgsqlValueGenerationStrategy" /> for a particular table.
/// </summary>
/// <param name="overrides">The property overrides.</param>
/// <returns>The <see cref="ConfigurationSource" /> for the <see cref="NpgsqlValueGenerationStrategy" />.</returns>
public static ConfigurationSource? GetValueGenerationStrategyConfigurationSource(
this IConventionRelationalPropertyOverrides overrides)
=> overrides.FindAnnotation(NpgsqlAnnotationNames.ValueGenerationStrategy)?.GetConfigurationSource();

/// <summary>
/// Returns a value indicating whether the property is compatible with any <see cref="NpgsqlValueGenerationStrategy" />.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,10 @@ public static DbContextOptionsBuilder UseNpgsql(
/// </returns>
public static DbContextOptionsBuilder UseNpgsql(
this DbContextOptionsBuilder optionsBuilder,
string connectionString,
string? connectionString,
Action<NpgsqlDbContextOptionsBuilder>? npgsqlOptionsAction = null)
{
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
Check.NotEmpty(connectionString, nameof(connectionString));

var extension = (NpgsqlOptionsExtension)GetOrCreateExtension(optionsBuilder).WithConnectionString(connectionString);
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
Expand Down Expand Up @@ -130,7 +129,7 @@ public static DbContextOptionsBuilder<TContext> UseNpgsql<TContext>(
/// </returns>
public static DbContextOptionsBuilder<TContext> UseNpgsql<TContext>(
this DbContextOptionsBuilder<TContext> optionsBuilder,
string connectionString,
string? connectionString,
Action<NpgsqlDbContextOptionsBuilder>? npgsqlOptionsAction = null)
where TContext : DbContext
=> (DbContextOptionsBuilder<TContext>)UseNpgsql(
Expand Down
4 changes: 2 additions & 2 deletions src/EFCore.PG/Extensions/NpgsqlServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ public static class NpgsqlServiceCollectionExtensions
/// <returns> The same service collection so that multiple calls can be chained. </returns>
public static IServiceCollection AddNpgsql<TContext>(
this IServiceCollection serviceCollection,
string connectionString, Action<NpgsqlDbContextOptionsBuilder>? npgsqlOptionsAction = null,
string? connectionString,
Action<NpgsqlDbContextOptionsBuilder>? npgsqlOptionsAction = null,
Action<DbContextOptionsBuilder>? optionsAction = null)
where TContext : DbContext
{
Check.NotNull(serviceCollection, nameof(serviceCollection));
Check.NotEmpty(connectionString, nameof(connectionString));

return serviceCollection.AddDbContext<TContext>((_, options) =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,24 @@ public virtual void ProcessModelFinalizing(
foreach (var property in entityType.GetDeclaredProperties())
{
NpgsqlValueGenerationStrategy? strategy = null;
var table = entityType.GetTableName();
if (table is not null)
var declaringTable = property.GetMappedStoreObjects(StoreObjectType.Table).FirstOrDefault();
if (declaringTable.Name != null!)
{
var storeObject = StoreObjectIdentifier.Table(table, entityType.GetSchema());
strategy = property.GetValueGenerationStrategy(storeObject, Dependencies.TypeMappingSource);
strategy = property.GetValueGenerationStrategy(declaringTable, Dependencies.TypeMappingSource);
if (strategy == NpgsqlValueGenerationStrategy.None
&& !IsStrategyNoneNeeded(property, storeObject))
&& !IsStrategyNoneNeeded(property, declaringTable))
{
strategy = null;
}
}
else
{
var view = entityType.GetViewName();
if (view is not null)
var declaringView = property.GetMappedStoreObjects(StoreObjectType.View).FirstOrDefault();
if (declaringView.Name != null!)
{
var storeObject = StoreObjectIdentifier.View(view, entityType.GetViewSchema());
strategy = property.GetValueGenerationStrategy(storeObject, Dependencies.TypeMappingSource);
strategy = property.GetValueGenerationStrategy(declaringView, Dependencies.TypeMappingSource);
if (strategy == NpgsqlValueGenerationStrategy.None
&& !IsStrategyNoneNeeded(property, storeObject))
&& !IsStrategyNoneNeeded(property, declaringView))
{
strategy = null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore.TestModels.ManyToManyFieldsModel;
using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query;
namespace Npgsql.EntityFrameworkCore.PostgreSQL;

public class ManyToManyFieldsLoadNpgsqlTest
: ManyToManyFieldsLoadTestBase<ManyToManyFieldsLoadNpgsqlTest.ManyToManyFieldsLoadNpgsqlFixture>
Expand Down Expand Up @@ -46,4 +46,4 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
.HasDefaultValue("Generated");
}
}
}
}
14 changes: 13 additions & 1 deletion test/EFCore.PG.FunctionalTests/ManyToManyLoadNpgsqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
.HasColumnType("timestamp without time zone")
.HasDefaultValueSql("NOW() AT TIME ZONE 'UTC'");

modelBuilder
.Entity<UnidirectionalEntityCompositeKey>()
.Property(e => e.Key3)
.HasColumnType("timestamp without time zone")
.HasDefaultValueSql("NOW() AT TIME ZONE 'UTC'");

modelBuilder
.Entity<UnidirectionalJoinOneSelfPayload>()
.Property(e => e.Payload)
.HasColumnType("timestamp without time zone")
.HasDefaultValueSql("NOW() AT TIME ZONE 'UTC'");

modelBuilder
.SharedTypeEntity<Dictionary<string, object>>("JoinOneToThreePayloadFullShared")
.IndexerProperty<string>("Payload")
Expand All @@ -42,4 +54,4 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
.HasDefaultValue("Generated");
}
}
}
}
Loading

0 comments on commit 9903e84

Please sign in to comment.