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 missing Model Builder API #34427

Merged
merged 1 commit into from
Aug 14, 2024
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
74 changes: 48 additions & 26 deletions src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,7 @@ public virtual bool EnsureCreated()
InsertData();
}

var coreOptionsExtension =
_contextOptions.FindExtension<CoreOptionsExtension>()
?? new CoreOptionsExtension();

var seed = coreOptionsExtension.Seeder;
if (seed != null)
{
seed(_currentContext.Context, created);
}
else if (coreOptionsExtension.AsyncSeeder != null)
{
throw new InvalidOperationException(CoreStrings.MissingSeeder);
}
SeedData(created);

return created;
}
Expand Down Expand Up @@ -104,19 +92,7 @@ public virtual async Task<bool> EnsureCreatedAsync(CancellationToken cancellatio
await InsertDataAsync(cancellationToken).ConfigureAwait(false);
}

var coreOptionsExtension =
_contextOptions.FindExtension<CoreOptionsExtension>()
?? new CoreOptionsExtension();

var seedAsync = coreOptionsExtension.AsyncSeeder;
if (seedAsync != null)
{
await seedAsync(_currentContext.Context, created, cancellationToken).ConfigureAwait(false);
}
else if (coreOptionsExtension.Seeder != null)
{
throw new InvalidOperationException(CoreStrings.MissingSeeder);
}
await SeedDataAsync(created, cancellationToken).ConfigureAwait(false);

return created;
}
Expand Down Expand Up @@ -223,6 +199,52 @@ private IUpdateAdapter AddModelData()
return updateAdapter;
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual void SeedData(bool created)
{
var coreOptionsExtension =
_contextOptions.FindExtension<CoreOptionsExtension>()
?? new CoreOptionsExtension();

var seed = coreOptionsExtension.Seeder;
if (seed != null)
{
seed(_currentContext.Context, created);
}
else if (coreOptionsExtension.AsyncSeeder != null)
{
throw new InvalidOperationException(CoreStrings.MissingSeeder);
}
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual async Task SeedDataAsync(bool created, CancellationToken cancellationToken = default)
{
var coreOptionsExtension =
_contextOptions.FindExtension<CoreOptionsExtension>()
?? new CoreOptionsExtension();

var seedAsync = coreOptionsExtension.AsyncSeeder;
if (seedAsync != null)
{
await seedAsync(_currentContext.Context, created, cancellationToken).ConfigureAwait(false);
}
else if (coreOptionsExtension.Seeder != null)
{
throw new InvalidOperationException(CoreStrings.MissingSeeder);
}
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,111 @@ public static bool CanSetIsMemoryOptimized(
bool fromDataAnnotation = false)
=> entityTypeBuilder.CanSetAnnotation(SqlServerAnnotationNames.MemoryOptimized, memoryOptimized, fromDataAnnotation);

/// <summary>
/// Sets a value indicating whether to use the SQL OUTPUT clause when saving changes to the table.
/// The OUTPUT clause is incompatible with certain SQL Server features, such as tables with triggers.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples.
/// </remarks>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="useSqlOutputClause">The value to set.</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 IConventionEntityTypeBuilder? UseSqlOutputClause(
this IConventionEntityTypeBuilder entityTypeBuilder,
bool? useSqlOutputClause,
bool fromDataAnnotation = false)
{
if (!entityTypeBuilder.CanUseSqlOutputClause(useSqlOutputClause, fromDataAnnotation))
{
return null;
}

entityTypeBuilder.Metadata.UseSqlOutputClause(useSqlOutputClause, fromDataAnnotation);
return entityTypeBuilder;
}

/// <summary>
/// Sets a value indicating whether to use the SQL OUTPUT clause when saving changes to the table.
/// The OUTPUT clause is incompatible with certain SQL Server features, such as tables with triggers.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples.
/// </remarks>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="useSqlOutputClause">The value to set.</param>
/// <param name="storeObject">The identifier of the table-like store object.</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 IConventionEntityTypeBuilder? UseSqlOutputClause(
this IConventionEntityTypeBuilder entityTypeBuilder,
bool? useSqlOutputClause,
in StoreObjectIdentifier storeObject,
bool fromDataAnnotation = false)
{
if (!entityTypeBuilder.CanUseSqlOutputClause(useSqlOutputClause, storeObject, fromDataAnnotation))
{
return null;
}

entityTypeBuilder.Metadata.UseSqlOutputClause(useSqlOutputClause, storeObject, fromDataAnnotation);
return entityTypeBuilder;
}

/// <summary>
/// Returns a value indicating whether this entity type can be configured to use the SQL OUTPUT clause
/// using the specified configuration source.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples.
/// </remarks>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="useSqlOutputClause">The value to set.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns><see langword="true" /> if the configuration can be applied.</returns>
public static bool CanUseSqlOutputClause(
this IConventionEntityTypeBuilder entityTypeBuilder,
bool? useSqlOutputClause,
bool fromDataAnnotation = false)
=> entityTypeBuilder.CanSetAnnotation(
SqlServerAnnotationNames.UseSqlOutputClause,
useSqlOutputClause,
fromDataAnnotation);

/// <summary>
/// Returns a value indicating whether this entity type can be configured to use the SQL OUTPUT clause
/// using the specified configuration source.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples.
/// </remarks>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="useSqlOutputClause">The value to set.</param>
/// <param name="storeObject">The identifier of the table-like store object.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns><see langword="true" /> if the configuration can be applied.</returns>
public static bool CanUseSqlOutputClause(
this IConventionEntityTypeBuilder entityTypeBuilder,
bool? useSqlOutputClause,
in StoreObjectIdentifier storeObject,
bool fromDataAnnotation = false)
=> StoreObjectIdentifier.Create(entityTypeBuilder.Metadata, storeObject.StoreObjectType) == storeObject
? entityTypeBuilder.CanSetAnnotation(
SqlServerAnnotationNames.UseSqlOutputClause,
useSqlOutputClause,
fromDataAnnotation)
: entityTypeBuilder.Metadata.GetOrCreateMappingFragment(storeObject, fromDataAnnotation).Builder.CanSetAnnotation(
SqlServerAnnotationNames.UseSqlOutputClause,
useSqlOutputClause,
fromDataAnnotation);

/// <summary>
/// Configures the table as temporal.
/// </summary>
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 Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal;

// ReSharper disable once CheckNamespace
Expand Down Expand Up @@ -344,6 +345,18 @@ public static void UseSqlOutputClause(this IMutableEntityType entityType, bool?
public static ConfigurationSource? GetUseSqlOutputClauseConfigurationSource(this IConventionEntityType entityType)
=> entityType.FindAnnotation(SqlServerAnnotationNames.UseSqlOutputClause)?.GetConfigurationSource();

/// <summary>
/// Gets the configuration source for whether to use the SQL OUTPUT clause when saving changes to the table.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="storeObject">The identifier of the table-like store object.</param>
/// <returns>The configuration source for the memory-optimized setting.</returns>
public static ConfigurationSource? GetUseSqlOutputClauseConfigurationSource(
this IConventionEntityType entityType, in StoreObjectIdentifier storeObject)
=> StoreObjectIdentifier.Create(entityType, storeObject.StoreObjectType) == storeObject
? entityType.GetUseSqlOutputClauseConfigurationSource()
: (entityType.FindMappingFragment(storeObject)?.GetUseSqlOutputClauseConfigurationSource());

/// <summary>
/// Returns a value indicating whether to use the SQL OUTPUT clause when saving changes to the specified table.
/// The OUTPUT clause is incompatible with certain SQL Server features, such as tables with triggers.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static bool IsSqlOutputClauseUsed(this IReadOnlyEntityTypeMappingFragment
/// <param name="fragment">The entity type mapping fragment.</param>
/// <param name="useSqlOutputClause">The value to set.</param>
public static void UseSqlOutputClause(this IMutableEntityTypeMappingFragment fragment, bool? useSqlOutputClause)
=> fragment.SetAnnotation(SqlServerAnnotationNames.UseSqlOutputClause, useSqlOutputClause);
=> fragment.SetOrRemoveAnnotation(SqlServerAnnotationNames.UseSqlOutputClause, useSqlOutputClause);

/// <summary>
/// Sets whether to use the SQL OUTPUT clause when saving changes to the associated table.
Expand All @@ -41,7 +41,7 @@ public static void UseSqlOutputClause(this IMutableEntityTypeMappingFragment fra
this IConventionEntityTypeMappingFragment fragment,
bool? useSqlOutputClause,
bool fromDataAnnotation = false)
=> (bool?)fragment.SetAnnotation(SqlServerAnnotationNames.UseSqlOutputClause, useSqlOutputClause, fromDataAnnotation)?.Value;
=> (bool?)fragment.SetOrRemoveAnnotation(SqlServerAnnotationNames.UseSqlOutputClause, useSqlOutputClause, fromDataAnnotation)?.Value;

/// <summary>
/// Gets the configuration source for the setting whether to use the SQL OUTPUT clause when saving changes to the associated table.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Sqlite.Metadata.Internal;

// ReSharper disable once CheckNamespace
namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Entity type builder extension methods for Sqlite-specific metadata.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-sqlite">Accessing Sqlite databases with EF Core</see> for more information and examples.
/// </remarks>
public static class SqliteEntityTypeBuilderExtensions
{
/// <summary>
/// Sets a value indicating whether to use the SQL RETURNING clause when saving changes to the table.
/// The RETURNING clause is incompatible with certain Sqlite features, such as virtual tables or tables with AFTER triggers.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples.
/// </remarks>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="useSqlReturningClause">The value to set.</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 IConventionEntityTypeBuilder? UseSqlReturningClause(
this IConventionEntityTypeBuilder entityTypeBuilder,
bool? useSqlReturningClause,
bool fromDataAnnotation = false)
{
if (!entityTypeBuilder.CanUseSqlReturningClause(useSqlReturningClause, fromDataAnnotation))
{
return null;
}

entityTypeBuilder.Metadata.UseSqlReturningClause(useSqlReturningClause, fromDataAnnotation);
return entityTypeBuilder;
}

/// <summary>
/// Sets a value indicating whether to use the SQL RETURNING clause when saving changes to the table.
/// The RETURNING clause is incompatible with certain Sqlite features, such as virtual tables or tables with AFTER triggers.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples.
/// </remarks>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="useSqlReturningClause">The value to set.</param>
/// <param name="storeObject">The identifier of the table-like store object.</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 IConventionEntityTypeBuilder? UseSqlReturningClause(
this IConventionEntityTypeBuilder entityTypeBuilder,
bool? useSqlReturningClause,
in StoreObjectIdentifier storeObject,
bool fromDataAnnotation = false)
{
if (!entityTypeBuilder.CanUseSqlReturningClause(useSqlReturningClause, storeObject, fromDataAnnotation))
{
return null;
}

entityTypeBuilder.Metadata.UseSqlReturningClause(useSqlReturningClause, storeObject, fromDataAnnotation);
return entityTypeBuilder;
}

/// <summary>
/// Returns a value indicating whether this entity type can be configured to use the SQL RETURNING clause
/// using the specified configuration source.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples.
/// </remarks>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="useSqlReturningClause">The value to set.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns><see langword="true" /> if the configuration can be applied.</returns>
public static bool CanUseSqlReturningClause(
this IConventionEntityTypeBuilder entityTypeBuilder,
bool? useSqlReturningClause,
bool fromDataAnnotation = false)
=> entityTypeBuilder.CanSetAnnotation(
SqliteAnnotationNames.UseSqlReturningClause,
useSqlReturningClause,
fromDataAnnotation);

/// <summary>
/// Returns a value indicating whether this entity type can be configured to use the SQL RETURNING clause
/// using the specified configuration source.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples.
/// </remarks>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="useSqlReturningClause">The value to set.</param>
/// <param name="storeObject">The identifier of the table-like store object.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns><see langword="true" /> if the configuration can be applied.</returns>
public static bool CanUseSqlReturningClause(
this IConventionEntityTypeBuilder entityTypeBuilder,
bool? useSqlReturningClause,
in StoreObjectIdentifier storeObject,
bool fromDataAnnotation = false)
=> StoreObjectIdentifier.Create(entityTypeBuilder.Metadata, storeObject.StoreObjectType) == storeObject
? entityTypeBuilder.CanSetAnnotation(
SqliteAnnotationNames.UseSqlReturningClause,
useSqlReturningClause,
fromDataAnnotation)
: entityTypeBuilder.Metadata.GetOrCreateMappingFragment(storeObject, fromDataAnnotation).Builder.CanSetAnnotation(
SqliteAnnotationNames.UseSqlReturningClause,
useSqlReturningClause,
fromDataAnnotation);
}
Loading