Skip to content

Commit

Permalink
Cosmos: Add API to configure the container that a hierarchy is mapped…
Browse files Browse the repository at this point in the history
… to, as well as the default container name

Enable materializing derived types polymorphically
Add exceptions for some unsupported cases
  • Loading branch information
AndriySvyryd committed Oct 12, 2018
1 parent 31e0e41 commit b8ad5cc
Show file tree
Hide file tree
Showing 55 changed files with 1,609 additions and 184 deletions.
1 change: 0 additions & 1 deletion src/EFCore.Abstractions/EFCore.Abstractions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
<ItemGroup>
<None Update="Properties\AbstractionsStrings.Designer.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<CustomToolNamespace>Microsoft.EntityFrameworkCore.Internal</CustomToolNamespace>
<LastGenOutput>AbstractionsStrings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
Expand Down
53 changes: 53 additions & 0 deletions src/EFCore.Cosmos/CosmosCollectionOwnershipBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Cosmos
{
/// <summary>
/// Cosmos specific extension methods for <see cref="CollectionOwnershipBuilder" />.
/// </summary>
public static class CosmosCollectionOwnershipBuilderExtensions
{
/// <summary>
/// Configures the container that the entity maps to when targeting Azure Cosmos.
/// </summary>
/// <param name="referenceOwnershipBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the container. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static CollectionOwnershipBuilder ToContainer(
[NotNull] this CollectionOwnershipBuilder referenceOwnershipBuilder,
[CanBeNull] string name)
{
Check.NotNull(referenceOwnershipBuilder, nameof(referenceOwnershipBuilder));
Check.NullButNotEmpty(name, nameof(name));

referenceOwnershipBuilder.GetInfrastructure<InternalEntityTypeBuilder>()
.Cosmos(ConfigurationSource.Explicit)
.ToContainer(name);

return referenceOwnershipBuilder;
}

/// <summary>
/// Configures the container that the entity maps to when targeting Azure Cosmos.
/// </summary>
/// <typeparam name="TEntity"> The entity type being configured. </typeparam>
/// <typeparam name="TDependentEntity"> The entity type that this relationship targets. </typeparam>
/// <param name="referenceOwnershipBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the container. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static CollectionOwnershipBuilder<TEntity, TDependentEntity> ToContainer<TEntity, TDependentEntity>(
[NotNull] this CollectionOwnershipBuilder<TEntity, TDependentEntity> referenceOwnershipBuilder,
[CanBeNull] string name)
where TEntity : class
where TDependentEntity : class
=> (CollectionOwnershipBuilder<TEntity, TDependentEntity>)ToContainer((CollectionOwnershipBuilder)referenceOwnershipBuilder, name);
}
}
52 changes: 52 additions & 0 deletions src/EFCore.Cosmos/CosmosEntityTypeBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Utilities;

// ReSharper disable once CheckNamespace
namespace Microsoft.EntityFrameworkCore
{
/// <summary>
/// Cosmos specific extension methods for <see cref="EntityTypeBuilder" />.
/// </summary>
public static class CosmosEntityTypeBuilderExtensions
{
/// <summary>
/// Configures the container that the entity maps to when targeting Azure Cosmos.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the container. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static EntityTypeBuilder ToContainer(
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name)
{
Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
Check.NullButNotEmpty(name, nameof(name));

entityTypeBuilder.GetInfrastructure<InternalEntityTypeBuilder>()
.Cosmos(ConfigurationSource.Explicit)
.ToContainer(name);

return entityTypeBuilder;
}

/// <summary>
/// Configures the container that the entity maps to when targeting Azure Cosmos.
/// </summary>
/// <typeparam name="TEntity"> The entity type being configured. </typeparam>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the container. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static EntityTypeBuilder<TEntity> ToContainer<TEntity>(
[NotNull] this EntityTypeBuilder<TEntity> entityTypeBuilder,
[CanBeNull] string name)
where TEntity : class
=> (EntityTypeBuilder<TEntity>)ToContainer((EntityTypeBuilder)entityTypeBuilder, name);
}
}
34 changes: 34 additions & 0 deletions src/EFCore.Cosmos/CosmosModelBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Utilities;

// ReSharper disable once CheckNamespace
namespace Microsoft.EntityFrameworkCore
{
public static class CosmosModelBuilderExtensions
{
/// <summary>
/// Configures the default container name that will be used if no name
/// is explicitly configured for an entity type.
/// </summary>
/// <param name="modelBuilder"> The model builder. </param>
/// <param name="name"> The default container name. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static ModelBuilder HasDefaultContainerName(
[NotNull] this ModelBuilder modelBuilder,
[CanBeNull] string name)
{
Check.NotNull(modelBuilder, nameof(modelBuilder));
Check.NullButNotEmpty(name, nameof(name));

modelBuilder.GetInfrastructure().Cosmos(ConfigurationSource.Explicit).HasDefaultContainerName(name);

return modelBuilder;
}
}
}
53 changes: 53 additions & 0 deletions src/EFCore.Cosmos/CosmosReferenceOwnershipBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Cosmos
{
/// <summary>
/// Cosmos specific extension methods for <see cref="ReferenceOwnershipBuilder" />.
/// </summary>
public static class CosmosReferenceOwnershipBuilderExtensions
{
/// <summary>
/// Configures the container that the entity maps to when targeting Azure Cosmos.
/// </summary>
/// <param name="referenceOwnershipBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the container. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static ReferenceOwnershipBuilder ToContainer(
[NotNull] this ReferenceOwnershipBuilder referenceOwnershipBuilder,
[CanBeNull] string name)
{
Check.NotNull(referenceOwnershipBuilder, nameof(referenceOwnershipBuilder));
Check.NullButNotEmpty(name, nameof(name));

referenceOwnershipBuilder.GetInfrastructure<InternalEntityTypeBuilder>()
.Cosmos(ConfigurationSource.Explicit)
.ToContainer(name);

return referenceOwnershipBuilder;
}

/// <summary>
/// Configures the container that the entity maps to when targeting Azure Cosmos.
/// </summary>
/// <typeparam name="TEntity"> The entity type being configured. </typeparam>
/// <typeparam name="TRelatedEntity"> The entity type that this relationship targets. </typeparam>
/// <param name="referenceOwnershipBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the container. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static ReferenceOwnershipBuilder<TEntity, TRelatedEntity> ToContainer<TEntity, TRelatedEntity>(
[NotNull] this ReferenceOwnershipBuilder<TEntity, TRelatedEntity> referenceOwnershipBuilder,
[CanBeNull] string name)
where TEntity : class
where TRelatedEntity : class
=> (ReferenceOwnershipBuilder<TEntity, TRelatedEntity>)ToContainer((ReferenceOwnershipBuilder)referenceOwnershipBuilder, name);
}
}
26 changes: 26 additions & 0 deletions src/EFCore.Cosmos/EFCore.Cosmos.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,30 @@
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
</ItemGroup>

<ItemGroup>
<Compile Update="Properties\CosmosStrings.Designer.cs">
<DependentUpon>CosmosStrings.Designer.tt</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
</ItemGroup>

<ItemGroup>
<None Update="Properties\CosmosStrings.Designer.tt">
<CustomToolNamespace></CustomToolNamespace>
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>CosmosStrings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>

<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Properties\CosmosStrings.resx">
<CustomToolNamespace>Microsoft.EntityFrameworkCore.Cosmos.Internal</CustomToolNamespace>
</EmbeddedResource>
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions src/EFCore.Cosmos/Extensions/CosmosMetadataExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ namespace Microsoft.EntityFrameworkCore
/// </summary>
public static class CosmosMetadataExtensions
{
/// <summary>
/// Gets the Cosmos-specific metadata for a model.
/// </summary>
/// <param name="model"> The model to get metadata for. </param>
/// <returns> The Cosmos-specific metadata for the model. </returns>
public static ICosmosModelAnnotations Cosmos(this IModel model)
=> new CosmosModelAnnotations(model);

/// <summary>
/// Gets the Cosmos-specific metadata for a model.
/// </summary>
/// <param name="model"> The model to get metadata for. </param>
/// <returns> The Cosmos-specific metadata for the model. </returns>
public static CosmosModelAnnotations Cosmos(this IMutableModel model)
=> (CosmosModelAnnotations)Cosmos((IModel)model);

/// <summary>
/// Gets the Cosmos-specific metadata for an entity type.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Cosmos.Infrastructure;
using Microsoft.EntityFrameworkCore.Cosmos.Infrastructure.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Conventions.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Query.ExpressionVisitors.Internal;
Expand All @@ -28,14 +29,14 @@ public static IServiceCollection AddEntityFrameworkCosmos([NotNull] this IServic
.TryAdd<IDatabase, CosmosDatabase>()
.TryAdd<IExecutionStrategyFactory, CosmosExecutionStrategyFactory>()
.TryAdd<IDbContextTransactionManager, CosmosTransactionManager>()
.TryAdd<IModelCustomizer, CosmosModelCustomizer>()
.TryAdd<IConventionSetBuilder, CosmosConventionSetBuilder>()
.TryAdd<IDatabaseCreator, CosmosDatabaseCreator>()
.TryAdd<IQueryContextFactory, CosmosQueryContextFactory>()
.TryAdd<IEntityQueryModelVisitorFactory, CosmosEntityQueryModelVisitorFactory>()
.TryAdd<IEntityQueryableExpressionVisitorFactory, CosmosEntityQueryableExpressionVisitorFactory>()
.TryAdd<IMemberAccessBindingExpressionVisitorFactory, CosmosMemberAccessBindingExpressionVisitorFactory>()
.TryAdd<INavigationRewritingExpressionVisitorFactory, CosmosNavigationRewritingExpressionVisitorFactory>()
.TryAdd<IEagerLoadingExpressionVisitorFactory, CosmosEagerLoadingExpressionVisitorFactory>()
.TryAddProviderSpecificServices(
b => b
.TryAddScoped<CosmosClient, CosmosClient>()
Expand Down
47 changes: 47 additions & 0 deletions src/EFCore.Cosmos/Infrastructure/CosmosModelCustomizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

namespace Microsoft.EntityFrameworkCore.Cosmos.Infrastructure
{
/// <summary>
/// <para>
/// Builds the model for a given context. This default implementation builds the model by calling
/// <see cref="DbContext.OnConfiguring(DbContextOptionsBuilder)" /> on the context.
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// </summary>
public class CosmosModelCustomizer : ModelCustomizer
{
public CosmosModelCustomizer(ModelCustomizerDependencies dependencies)
: base(dependencies)
{
}

/// <summary>
/// <para>
/// Performs additional configuration of the model in addition to what is discovered by convention. This implementation
/// builds the model for a given context by calling <see cref="DbContext.OnConfiguring(DbContextOptionsBuilder)" />
/// on the context.
/// </para>
/// </summary>
/// <param name="modelBuilder">
/// The builder being used to construct the model.
/// </param>
/// <param name="context">
/// The context instance that the model is being created for.
/// </param>
public override void Customize(ModelBuilder modelBuilder, DbContext context)
{
modelBuilder.GetInfrastructure().Cosmos(ConfigurationSource.Convention).HasDefaultContainerName(context.GetType().Name);

base.Customize(modelBuilder, context);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ public class CosmosConventionSetBuilder : IConventionSetBuilder
public ConventionSet AddConventions(ConventionSet conventionSet)
{
var discriminatorConvention = new DiscriminatorConvention();

var storeKeyConvention = new StoreKeyConvention();
conventionSet.EntityTypeAddedConventions.Add(storeKeyConvention);
conventionSet.EntityTypeAddedConventions.Add(discriminatorConvention);

conventionSet.BaseEntityTypeChangedConventions.Add(storeKeyConvention);
conventionSet.BaseEntityTypeChangedConventions.Add(discriminatorConvention);

conventionSet.ForeignKeyOwnershipChangedConventions.Add(storeKeyConvention);

conventionSet.EntityTypeAnnotationChangedConventions.Add(storeKeyConvention);

return conventionSet;
}
}
Expand Down

0 comments on commit b8ad5cc

Please sign in to comment.