11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4+ using Microsoft . EntityFrameworkCore . SqlServer . Internal ;
45using Microsoft . EntityFrameworkCore . SqlServer . Metadata . Internal ;
56
67// ReSharper disable once CheckNamespace
@@ -18,6 +19,8 @@ public static class SqlServerEntityTypeExtensions
1819{
1920 private const string DefaultHistoryTableNameSuffix = "History" ;
2021
22+ #region Memory-optimized table
23+
2124 /// <summary>
2225 /// Returns a value indicating whether the entity type is mapped to a memory-optimized table.
2326 /// </summary>
@@ -58,6 +61,10 @@ public static void SetIsMemoryOptimized(this IMutableEntityType entityType, bool
5861 public static ConfigurationSource ? GetIsMemoryOptimizedConfigurationSource ( this IConventionEntityType entityType )
5962 => entityType . FindAnnotation ( SqlServerAnnotationNames . MemoryOptimized ) ? . GetConfigurationSource ( ) ;
6063
64+ #endregion Memory-optimized table
65+
66+ #region Temporal table
67+
6168 /// <summary>
6269 /// Returns a value indicating whether the entity type is mapped to a temporal table.
6370 /// </summary>
@@ -271,4 +278,149 @@ public static void SetHistoryTableSchema(this IMutableEntityType entityType, str
271278 /// <returns>The configuration source for the temporal history table schema setting.</returns>
272279 public static ConfigurationSource ? GetHistoryTableSchemaConfigurationSource ( this IConventionEntityType entityType )
273280 => entityType . FindAnnotation ( SqlServerAnnotationNames . TemporalHistoryTableSchema ) ? . GetConfigurationSource ( ) ;
281+
282+ #endregion Temporal table
283+
284+ #region SQL OUTPUT clause
285+
286+ /// <summary>
287+ /// Returns a value indicating whether to use the SQL OUTPUT clause when saving changes to the table.
288+ /// The OUTPUT clause is incompatible with certain SQL Server features, such as tables with triggers.
289+ /// </summary>
290+ /// <param name="entityType">The entity type.</param>
291+ /// <returns><see langword="true" /> if the SQL OUTPUT clause is used to save changes to the table.</returns>
292+ public static bool IsSqlOutputClauseUsed ( this IReadOnlyEntityType entityType )
293+ {
294+ if ( entityType . FindAnnotation ( SqlServerAnnotationNames . UseSqlOutputClause ) is { Value : bool useSqlOutputClause } )
295+ {
296+ return useSqlOutputClause ;
297+ }
298+
299+ if ( entityType . FindOwnership ( ) is { } ownership
300+ && StoreObjectIdentifier . Create ( entityType , StoreObjectType . Table ) is { } tableIdentifier
301+ && ownership . FindSharedObjectRootForeignKey ( tableIdentifier ) is { } rootForeignKey )
302+ {
303+ return rootForeignKey . PrincipalEntityType . IsSqlOutputClauseUsed ( ) ;
304+ }
305+
306+ if ( entityType . BaseType is not null && entityType . GetMappingStrategy ( ) == RelationalAnnotationNames . TphMappingStrategy )
307+ {
308+ return entityType . GetRootType ( ) . IsSqlOutputClauseUsed ( ) ;
309+ }
310+
311+ return true ;
312+ }
313+
314+ /// <summary>
315+ /// Sets a value indicating whether to use the SQL OUTPUT clause when saving changes to the table.
316+ /// The OUTPUT clause is incompatible with certain SQL Server features, such as tables with triggers.
317+ /// </summary>
318+ /// <param name="entityType">The entity type.</param>
319+ /// <param name="useSqlOutputClause">The value to set.</param>
320+ public static void UseSqlOutputClause ( this IMutableEntityType entityType , bool ? useSqlOutputClause )
321+ => entityType . SetOrRemoveAnnotation ( SqlServerAnnotationNames . UseSqlOutputClause , useSqlOutputClause ) ;
322+
323+ /// <summary>
324+ /// Sets a value indicating whether to use the SQL OUTPUT clause when saving changes to the table.
325+ /// The OUTPUT clause is incompatible with certain SQL Server features, such as tables with triggers.
326+ /// </summary>
327+ /// <param name="entityType">The entity type.</param>
328+ /// <param name="useSqlOutputClause">The value to set.</param>
329+ /// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
330+ /// <returns>The configured value.</returns>
331+ public static bool ? UseSqlOutputClause (
332+ this IConventionEntityType entityType ,
333+ bool ? useSqlOutputClause ,
334+ bool fromDataAnnotation = false )
335+ => ( bool ? ) entityType . SetOrRemoveAnnotation (
336+ SqlServerAnnotationNames . UseSqlOutputClause ,
337+ useSqlOutputClause ,
338+ fromDataAnnotation ) ? . Value ;
339+
340+ /// <summary>
341+ /// Gets the configuration source for whether to use the SQL OUTPUT clause when saving changes to the table.
342+ /// </summary>
343+ /// <param name="entityType">The entity type.</param>
344+ /// <returns>The configuration source for the memory-optimized setting.</returns>
345+ public static ConfigurationSource ? GetUseSqlOutputClauseConfigurationSource ( this IConventionEntityType entityType )
346+ => entityType . FindAnnotation ( SqlServerAnnotationNames . UseSqlOutputClause ) ? . GetConfigurationSource ( ) ;
347+
348+ /// <summary>
349+ /// Returns a value indicating whether to use the SQL OUTPUT clause when saving changes to the specified table.
350+ /// The OUTPUT clause is incompatible with certain SQL Server features, such as tables with triggers.
351+ /// </summary>
352+ /// <param name="entityType">The entity type.</param>
353+ /// <param name="storeObject">The identifier of the table-like store object.</param>
354+ /// <returns>A value indicating whether the SQL OUTPUT clause is used to save changes to the associated table.</returns>
355+ public static bool IsSqlOutputClauseUsed ( this IReadOnlyEntityType entityType , in StoreObjectIdentifier storeObject )
356+ {
357+ if ( entityType . FindMappingFragment ( storeObject ) is { } overrides
358+ && overrides . FindAnnotation ( SqlServerAnnotationNames . UseSqlOutputClause ) is { Value : bool useSqlOutputClause } )
359+ {
360+ return useSqlOutputClause ;
361+ }
362+
363+ if ( StoreObjectIdentifier . Create ( entityType , storeObject . StoreObjectType ) == storeObject )
364+ {
365+ return entityType . IsSqlOutputClauseUsed ( ) ;
366+ }
367+
368+ if ( entityType . FindOwnership ( ) is { } ownership
369+ && ownership . FindSharedObjectRootForeignKey ( storeObject ) is { } rootForeignKey )
370+ {
371+ return rootForeignKey . PrincipalEntityType . IsSqlOutputClauseUsed ( storeObject ) ;
372+ }
373+
374+ if ( entityType . BaseType is not null && entityType . GetMappingStrategy ( ) == RelationalAnnotationNames . TphMappingStrategy )
375+ {
376+ return entityType . GetRootType ( ) . IsSqlOutputClauseUsed ( storeObject ) ;
377+ }
378+
379+ return true ;
380+ }
381+
382+ /// <summary>
383+ /// Sets a value indicating whether to use the SQL OUTPUT clause when saving changes to the table.
384+ /// The OUTPUT clause is incompatible with certain SQL Server features, such as tables with triggers.
385+ /// </summary>
386+ /// <param name="entityType">The entity type.</param>
387+ /// <param name="useSqlOutputClause">The value to set.</param>
388+ /// <param name="storeObject">The identifier of the table-like store object.</param>
389+ public static void UseSqlOutputClause (
390+ this IMutableEntityType entityType ,
391+ bool ? useSqlOutputClause ,
392+ in StoreObjectIdentifier storeObject )
393+ {
394+ if ( StoreObjectIdentifier . Create ( entityType , storeObject . StoreObjectType ) == storeObject )
395+ {
396+ entityType . UseSqlOutputClause ( useSqlOutputClause ) ;
397+ return ;
398+ }
399+
400+ entityType
401+ . GetOrCreateMappingFragment ( storeObject )
402+ . UseSqlOutputClause ( useSqlOutputClause ) ;
403+ }
404+
405+ /// <summary>
406+ /// Sets a value indicating whether to use the SQL OUTPUT clause when saving changes to the table.
407+ /// The OUTPUT clause is incompatible with certain SQL Server features, such as tables with triggers.
408+ /// </summary>
409+ /// <param name="entityType">The entity type.</param>
410+ /// <param name="useSqlOutputClause">The value to set.</param>
411+ /// <param name="storeObject">The identifier of the table-like store object.</param>
412+ /// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
413+ /// <returns>The configured value.</returns>
414+ public static bool ? UseSqlOutputClause (
415+ this IConventionEntityType entityType ,
416+ bool ? useSqlOutputClause ,
417+ in StoreObjectIdentifier storeObject ,
418+ bool fromDataAnnotation = false )
419+ => StoreObjectIdentifier . Create ( entityType , storeObject . StoreObjectType ) == storeObject
420+ ? entityType . UseSqlOutputClause ( useSqlOutputClause , fromDataAnnotation )
421+ : entityType
422+ . GetOrCreateMappingFragment ( storeObject , fromDataAnnotation )
423+ . UseSqlOutputClause ( useSqlOutputClause , fromDataAnnotation ) ;
424+
425+ #endregion SQL OUTPUT clause
274426}
0 commit comments