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

Allow mapping entity types to SQL queries #21681

Merged
merged 1 commit into from
Jul 20, 2020
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
Expand Up @@ -44,7 +44,7 @@ public static EntityTypeBuilder<TEntity> ToQuery<TEntity>(
/// <returns>
/// The same builder instance if the query was set, <see langword="null" /> otherwise.
/// </returns>
public static IConventionEntityTypeBuilder HasDefiningQuery(
public static IConventionEntityTypeBuilder ToQuery(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder,
[CanBeNull] LambdaExpression query,
bool fromDataAnnotation = false)
Expand Down
5 changes: 4 additions & 1 deletion src/EFCore.Relational/Design/AnnotationCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ public class AnnotationCodeGenerator : IAnnotationCodeGenerator
RelationalAnnotationNames.CheckConstraints,
RelationalAnnotationNames.Sequences,
RelationalAnnotationNames.DbFunctions,
RelationalAnnotationNames.DefaultMappings,
RelationalAnnotationNames.DefaultColumnMappings,
RelationalAnnotationNames.TableMappings,
RelationalAnnotationNames.TableColumnMappings,
RelationalAnnotationNames.ViewMappings,
RelationalAnnotationNames.ViewColumnMappings,
RelationalAnnotationNames.FunctionMappings,
RelationalAnnotationNames.FunctionColumnMappings,
RelationalAnnotationNames.SqlQueryMappings,
RelationalAnnotationNames.SqlQueryColumnMappings,
RelationalAnnotationNames.ForeignKeyMappings,
RelationalAnnotationNames.TableIndexMappings,
RelationalAnnotationNames.UniqueConstraintMappings,
Expand Down Expand Up @@ -83,7 +87,6 @@ public virtual void RemoveAnnotationsHandledByConventions(
IProperty property, IDictionary<string, IAnnotation> annotations)
{
var columnName = property.GetColumnName();

if (columnName == property.Name)
{
annotations.Remove(RelationalAnnotationNames.ColumnName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
Expand Down Expand Up @@ -282,8 +281,7 @@ public static OwnedNavigationBuilder<TEntity, TRelatedEntity> ToTable<TEntity, T
/// <param name="name"> The name of the table. </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.
/// The same builder instance if the configuration was applied, <see langword="null" /> otherwise.
/// </returns>
public static IConventionEntityTypeBuilder ToTable(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] string name, bool fromDataAnnotation = false)
Expand All @@ -305,8 +303,7 @@ public static IConventionEntityTypeBuilder ToTable(
/// <param name="schema"> The schema of the table. </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.
/// The same builder instance if the configuration was applied, <see langword="null" /> otherwise.
/// </returns>
public static IConventionEntityTypeBuilder ToTable(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder,
Expand All @@ -325,11 +322,11 @@ public static IConventionEntityTypeBuilder ToTable(
}

/// <summary>
/// Returns a value indicating whether the view or table name can be set for this entity type
/// Returns a value indicating whether the table name can be set for this entity type
/// using the specified configuration source.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the view or table. </param>
/// <param name="name"> The name of the table. </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 CanSetTable(
Expand All @@ -341,14 +338,13 @@ public static bool CanSetTable(
}

/// <summary>
/// Configures the schema of the view or table that the entity type maps to when targeting a relational database.
/// Configures the schema of the table that the entity type maps to when targeting a relational database.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="schema"> The schema of the view or table. </param>
/// <param name="schema"> The schema of the table. </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.
/// The same builder instance if the configuration was applied, <see langword="null" /> otherwise.
/// </returns>
public static IConventionEntityTypeBuilder ToSchema(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder,
Expand All @@ -365,11 +361,11 @@ public static IConventionEntityTypeBuilder ToSchema(
}

/// <summary>
/// Returns a value indicating whether the schema of the view or table name can be set for this entity type
/// Returns a value indicating whether the schema of the table name can be set for this entity type
/// using the specified configuration source.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="schema"> The schema of the view or table. </param>
/// <param name="schema"> The schema of the table. </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 CanSetSchema(
Expand Down Expand Up @@ -481,6 +477,167 @@ public static EntityTypeBuilder<TEntity> ToView<TEntity>(
where TEntity : class
=> (EntityTypeBuilder<TEntity>)ToView((EntityTypeBuilder)entityTypeBuilder, name, schema);

/// <summary>
/// Configures the view that the entity type maps to when targeting a relational database.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the view. </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 ToView(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] string name, bool fromDataAnnotation = false)
{
if (!entityTypeBuilder.CanSetView(name, fromDataAnnotation))
{
return null;
}

entityTypeBuilder.Metadata.SetViewName(name, fromDataAnnotation);
return entityTypeBuilder;
}

/// <summary>
/// Configures the view that the entity type maps to when targeting a relational database.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the view. </param>
/// <param name="schema"> The schema of the view. </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 ToView(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name, [CanBeNull] string schema,
bool fromDataAnnotation = false)
{
if (!entityTypeBuilder.CanSetView(name, fromDataAnnotation)
|| !entityTypeBuilder.CanSetViewSchema(schema, fromDataAnnotation))
{
return null;
}

entityTypeBuilder.Metadata.SetViewName(name, fromDataAnnotation);
entityTypeBuilder.Metadata.SetViewSchema(schema, fromDataAnnotation);
return entityTypeBuilder;
}

/// <summary>
/// Returns a value indicating whether the view name can be set for this entity type
/// using the specified configuration source.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the view. </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 CanSetView(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] string name, bool fromDataAnnotation = false)
{
Check.NullButNotEmpty(name, nameof(name));

return entityTypeBuilder.CanSetAnnotation(RelationalAnnotationNames.ViewName, name, fromDataAnnotation);
}

/// <summary>
/// Configures the schema of the view that the entity type maps to when targeting a relational database.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="schema"> The schema of the view. </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 ToViewSchema(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder,
[CanBeNull] string schema,
bool fromDataAnnotation = false)
{
if (!entityTypeBuilder.CanSetSchema(schema, fromDataAnnotation))
{
return null;
}

entityTypeBuilder.Metadata.SetViewSchema(schema, fromDataAnnotation);
return entityTypeBuilder;
}

/// <summary>
/// Returns a value indicating whether the schema of the view can be set for this entity type
/// using the specified configuration source.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="schema"> The schema of the view. </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 CanSetViewSchema(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder,
[CanBeNull] string schema,
bool fromDataAnnotation = false)
{
Check.NullButNotEmpty(schema, nameof(schema));

return entityTypeBuilder.CanSetAnnotation(RelationalAnnotationNames.ViewSchema, schema, fromDataAnnotation);
}

/// <summary>
/// Configures a SQL string used to provide data for the entity type.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="query"> The SQL query that will provide the underlying data for the entity type. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static EntityTypeBuilder<TEntity> ToQuerySql<TEntity>(
[NotNull] this EntityTypeBuilder<TEntity> entityTypeBuilder,
[NotNull] string query)
where TEntity : class
{
Check.NotNull(query, nameof(query));

entityTypeBuilder.Metadata.SetQuerySql(query);

return entityTypeBuilder;
}

/// <summary>
/// Configures a SQL string used to provide data for the entity type.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The SQL query that will provide the underlying data for the entity type. </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 ToQuerySql(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] string name, bool fromDataAnnotation = false)
{
if (!entityTypeBuilder.CanSetQuerySql(name, fromDataAnnotation))
{
return null;
}

var entityType = entityTypeBuilder.Metadata;
entityType.SetQuerySql(name, fromDataAnnotation);

return entityTypeBuilder;
}

/// <summary>
/// Returns a value indicating whether the query SQL string can be set for this entity type
/// using the specified configuration source.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The SQL query that will provide the underlying data for the entity type. </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 CanSetQuerySql(
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] string name, bool fromDataAnnotation = false)
{
Check.NullButNotEmpty(name, nameof(name));

return entityTypeBuilder.CanSetAnnotation(RelationalAnnotationNames.QuerySql, name, fromDataAnnotation);
}

/// <summary>
/// Configures the function that the entity type maps to when targeting a relational database.
/// </summary>
Expand Down
Loading