Skip to content

Commit

Permalink
Integrate hierarchyid into the EF Core codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
bricelam committed Feb 14, 2023
1 parent 7caf9c4 commit 0adf618
Show file tree
Hide file tree
Showing 41 changed files with 1,211 additions and 1,215 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>EntityFrameworkCore.SqlServer.HierarchyId.Abstractions</AssemblyName>
<TargetFramework>netstandard2.1</TargetFramework>
<MinClientVersion>3.6</MinClientVersion>
<AssemblyName>Microsoft.EntityFrameworkCore.SqlServer.Abstractions</AssemblyName>
<RootNamespace>Microsoft.EntityFrameworkCore</RootNamespace>
<Description>Common abstractions for using hierarchyid with EF Core</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>$(PackageTags);SQL Server;HierarchyId</PackageTags>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="dotMorten.Microsoft.SqlServer.Types" Version="1.5.0" />
<PackageReference Include="Microsoft.SqlServer.Types" Version="160.1000.6" />
</ItemGroup>

</Project>
379 changes: 189 additions & 190 deletions src/EFCore.SqlServer.Abstractions/HierarchyId.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
using Microsoft.EntityFrameworkCore.Design;
// 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.Design;
using Microsoft.EntityFrameworkCore.Scaffolding;
using Microsoft.EntityFrameworkCore.SqlServer.Scaffolding;
using Microsoft.EntityFrameworkCore.SqlServer.Storage;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.EntityFrameworkCore.SqlServer.Design
namespace Microsoft.EntityFrameworkCore.SqlServer.Design;

/// <summary>
/// Enables configuring design-time services. Tools will automatically discover implementations of this
/// interface that are in the startup assembly.
/// </summary>
public class SqlServerHierarchyIdDesignTimeServices : IDesignTimeServices
{
/// <summary>
/// Enables configuring design-time services. Tools will automatically discover implementations of this
/// interface that are in the startup assembly.
/// Configures design-time services. Use this method to override the default design-time services with your
/// own implementations.
/// </summary>
public class SqlServerHierarchyIdDesignTimeServices : IDesignTimeServices
/// <param name="serviceCollection"> The design-time service collection. </param>
public virtual void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
{
/// <summary>
/// Configures design-time services. Use this method to override the default design-time services with your
/// own implementations.
/// </summary>
/// <param name="serviceCollection"> The design-time service collection. </param>
public virtual void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
{
serviceCollection
.AddSingleton<IRelationalTypeMappingSourcePlugin, SqlServerHierarchyIdTypeMappingSourcePlugin>()
.AddSingleton<IProviderCodeGeneratorPlugin, SqlServerHierarchyIdCodeGeneratorPlugin>();
}
serviceCollection
.AddSingleton<IRelationalTypeMappingSourcePlugin, SqlServerHierarchyIdTypeMappingSourcePlugin>()
.AddSingleton<IProviderCodeGeneratorPlugin, SqlServerHierarchyIdCodeGeneratorPlugin>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AssemblyName>EntityFrameworkCore.SqlServer.HierarchyId</AssemblyName>
<MinClientVersion>3.6</MinClientVersion>
<AssemblyName>Microsoft.EntityFrameworkCore.SqlServer.HierarchyId</AssemblyName>
<RootNamespace>Microsoft.EntityFrameworkCore.SqlServer</RootNamespace>
<Description>Adds hierarchyid support to the SQL Server EF Core provider</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>$(PackageTags);SQL Server;HierarchyId</PackageTags>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<Using Include="System.Diagnostics" />
<Using Include="System.Reflection" />
<Using Include="Microsoft.EntityFrameworkCore.Diagnostics" />
</ItemGroup>

<ItemGroup>
<Compile Include="..\Shared\*.cs" />
</ItemGroup>

<ItemGroup>
<None Include="build\**\*">
<Pack>True</Pack>
Expand All @@ -17,26 +29,29 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0" />
<ProjectReference Include="..\EFCore.SqlServer\EFCore.SqlServer.csproj" PrivateAssets="contentfiles;build" />
<ProjectReference Include="..\EFCore.SqlServer.Abstractions\EFCore.SqlServer.Abstractions.csproj" />
<ProjectReference Condition="'$(BuildingByReSharper)' != 'true'" Include="..\EFCore.Analyzers\EFCore.Analyzers.csproj" ReferenceOutputAssembly="False" OutputItemType="Analyzer" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\EFCore.SqlServer.HierarchyId.Abstractions\EFCore.SqlServer.HierarchyId.Abstractions.csproj" />
<None Update="Properties\SqlServerHierarchyIdStrings.Designer.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>SqlServerHierarchyIdStrings.Designer.cs</LastGenOutput>
<CustomToolNamespace>Microsoft.EntityFrameworkCore.SqlServer.Internal</CustomToolNamespace>
</None>
</ItemGroup>

<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Update="Properties\SqlServerHierarchyIdStrings.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>SqlServerHierarchyIdStrings.Designer.tt</DependentUpon>
</Compile>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
// 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.Infrastructure;
using Microsoft.EntityFrameworkCore.SqlServer.Infrastructure;

namespace Microsoft.EntityFrameworkCore
namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// HierarchyId specific extension methods for <see cref="SqlServerDbContextOptionsBuilder"/>.
/// </summary>
public static class SqlServerHierarchyIdDbContextOptionsBuilderExtensions
{
/// <summary>
/// HierarchyId specific extension methods for <see cref="SqlServerDbContextOptionsBuilder"/>.
/// Enable HierarchyId mappings.
/// </summary>
public static class SqlServerHierarchyIdDbContextOptionsBuilderExtensions
/// <param name="optionsBuilder">The builder being used to configure SQL Server.</param>
/// <returns>The options builder so that further configuration can be chained.</returns>
public static SqlServerDbContextOptionsBuilder UseHierarchyId(
this SqlServerDbContextOptionsBuilder optionsBuilder)
{
/// <summary>
/// Enable HierarchyId mappings.
/// </summary>
/// <param name="optionsBuilder">The builder being used to configure SQL Server.</param>
/// <returns>The options builder so that further configuration can be chained.</returns>
public static SqlServerDbContextOptionsBuilder UseHierarchyId(
this SqlServerDbContextOptionsBuilder optionsBuilder)
{
var coreOptionsBuilder = ((IRelationalDbContextOptionsBuilderInfrastructure)optionsBuilder).OptionsBuilder;
var coreOptionsBuilder = ((IRelationalDbContextOptionsBuilderInfrastructure)optionsBuilder).OptionsBuilder;

var extension = coreOptionsBuilder.Options.FindExtension<SqlServerHierarchyIdOptionsExtension>()
?? new SqlServerHierarchyIdOptionsExtension();
var extension = coreOptionsBuilder.Options.FindExtension<SqlServerHierarchyIdOptionsExtension>()
?? new SqlServerHierarchyIdOptionsExtension();

((IDbContextOptionsBuilderInfrastructure)coreOptionsBuilder).AddOrUpdateExtension(extension);
((IDbContextOptionsBuilderInfrastructure)coreOptionsBuilder).AddOrUpdateExtension(extension);

return optionsBuilder;
}
return optionsBuilder;
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
// 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.Infrastructure;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.SqlServer.Query.ExpressionTranslators;
using Microsoft.EntityFrameworkCore.SqlServer.Storage;
using Microsoft.EntityFrameworkCore.Storage;

namespace Microsoft.Extensions.DependencyInjection
namespace Microsoft.Extensions.DependencyInjection;

/// <summary>
/// EntityFrameworkCore.SqlServer.HierarchyId extension methods for <see cref="IServiceCollection"/>.
/// </summary>
public static class SqlServerHierarchyIdServiceCollectionExtensions
{
/// <summary>
/// EntityFrameworkCore.SqlServer.HierarchyId extension methods for <see cref="IServiceCollection"/>.
/// Adds the services required for HierarchyId support in the SQL Server provider for Entity Framework.
/// </summary>
public static class SqlServerHierarchyIdServiceCollectionExtensions
/// <param name="serviceCollection">The <see cref="IServiceCollection"/> to add services to.</param>
/// <returns>The same service collection so that multiple calls can be chained.</returns>
public static IServiceCollection AddEntityFrameworkSqlServerHierarchyId(
this IServiceCollection serviceCollection)
{
/// <summary>
/// Adds the services required for HierarchyId support in the SQL Server provider for Entity Framework.
/// </summary>
/// <param name="serviceCollection">The <see cref="IServiceCollection"/> to add services to.</param>
/// <returns>The same service collection so that multiple calls can be chained.</returns>
public static IServiceCollection AddEntityFrameworkSqlServerHierarchyId(
this IServiceCollection serviceCollection)
{
new EntityFrameworkRelationalServicesBuilder(serviceCollection)
.TryAdd<IMethodCallTranslatorPlugin, SqlServerHierarchyIdMethodCallTranslatorPlugin>()
.TryAdd<IRelationalTypeMappingSourcePlugin, SqlServerHierarchyIdTypeMappingSourcePlugin>();
new EntityFrameworkRelationalServicesBuilder(serviceCollection)
.TryAdd<IMethodCallTranslatorPlugin, SqlServerHierarchyIdMethodCallTranslatorPlugin>()
.TryAdd<IRelationalTypeMappingSourcePlugin, SqlServerHierarchyIdTypeMappingSourcePlugin>();

return serviceCollection;
}
return serviceCollection;
}
}
Original file line number Diff line number Diff line change
@@ -1,66 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
// 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.Infrastructure;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.SqlServer.Properties;
using Microsoft.EntityFrameworkCore.SqlServer.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Query.ExpressionTranslators;
using Microsoft.EntityFrameworkCore.SqlServer.Storage;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.EntityFrameworkCore.SqlServer.Infrastructure
namespace Microsoft.EntityFrameworkCore.SqlServer.Infrastructure;

internal class SqlServerHierarchyIdOptionsExtension : IDbContextOptionsExtension
{
internal class SqlServerHierarchyIdOptionsExtension : IDbContextOptionsExtension
{
private DbContextOptionsExtensionInfo _info;
private DbContextOptionsExtensionInfo? _info;

public DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this);
public DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this);

public virtual void ApplyServices(IServiceCollection services)
{
services.AddEntityFrameworkSqlServerHierarchyId();
}
public virtual void ApplyServices(IServiceCollection services)
{
services.AddEntityFrameworkSqlServerHierarchyId();
}

public virtual void Validate(IDbContextOptions options)
public virtual void Validate(IDbContextOptions options)
{
var internalServiceProvider = options.FindExtension<CoreOptionsExtension>()?.InternalServiceProvider;
if (internalServiceProvider != null)
{
var internalServiceProvider = options.FindExtension<CoreOptionsExtension>()?.InternalServiceProvider;
if (internalServiceProvider != null)
using (var scope = internalServiceProvider.CreateScope())
{
using (var scope = internalServiceProvider.CreateScope())
if (scope.ServiceProvider.GetService<IEnumerable<IMethodCallTranslatorPlugin>>()
?.Any(s => s is SqlServerHierarchyIdMethodCallTranslatorPlugin) != true ||
scope.ServiceProvider.GetService<IEnumerable<IRelationalTypeMappingSourcePlugin>>()
?.Any(s => s is SqlServerHierarchyIdTypeMappingSourcePlugin) != true)
{
if (scope.ServiceProvider.GetService<IEnumerable<IMethodCallTranslatorPlugin>>()
?.Any(s => s is SqlServerHierarchyIdMethodCallTranslatorPlugin) != true ||
scope.ServiceProvider.GetService<IEnumerable<IRelationalTypeMappingSourcePlugin>>()
?.Any(s => s is SqlServerHierarchyIdTypeMappingSourcePlugin) != true)
{
throw new InvalidOperationException(Resources.ServicesMissing);
}
throw new InvalidOperationException(SqlServerHierarchyIdStrings.ServicesMissing);
}
}
}
}

private sealed class ExtensionInfo : DbContextOptionsExtensionInfo
private sealed class ExtensionInfo : DbContextOptionsExtensionInfo
{
public ExtensionInfo(IDbContextOptionsExtension extension)
: base(extension)
{
public ExtensionInfo(IDbContextOptionsExtension extension)
: base(extension)
{
}
}

private new SqlServerHierarchyIdOptionsExtension Extension
=> (SqlServerHierarchyIdOptionsExtension)base.Extension;
private new SqlServerHierarchyIdOptionsExtension Extension
=> (SqlServerHierarchyIdOptionsExtension)base.Extension;

public override bool IsDatabaseProvider => false;
public override bool IsDatabaseProvider => false;

public override int GetServiceProviderHashCode() => 0;
public override int GetServiceProviderHashCode() => 0;

public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
=> other is ExtensionInfo;
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
=> other is ExtensionInfo;

public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
=> debugInfo["SqlServer:" + nameof(SqlServerHierarchyIdDbContextOptionsBuilderExtensions.UseHierarchyId)] = "1";
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
=> debugInfo["SqlServer:" + nameof(SqlServerHierarchyIdDbContextOptionsBuilderExtensions.UseHierarchyId)] = "1";

public override string LogFragment => "using HierarchyId ";
}
public override string LogFragment => "using HierarchyId ";
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System.Runtime.CompilerServices;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo(
"EntityFrameworkCore.SqlServer.HierarchyId.Test, PublicKey=00240000048000009400000006020000002400005253413100040000010001006d92138307b5e251bf4918cf751dc83489f4b2d70ac15b04110fd1f78491fe93719d0cd464d103a95fb1c3b1cb21ce0033c94c6f52b325d36360736dea7571bd1074cb2c937cf4fc54526ceb44271c4f44753dbeb5d9b364e4dc57a8988542d3a7edb6575bc35ce7670612bd8f00f2c6899f3e74bd563810fa45f4c5c8b51cd3")]
"Microsoft.EntityFrameworkCore.SqlServer.HierarchyId.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
Loading

0 comments on commit 0adf618

Please sign in to comment.