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

A bit of cleanup and fix a bug where UseStrictTyping didn't flow through specs #454

Merged
merged 2 commits into from
Jun 30, 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
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<PropertyGroup>
<CompatibilityTargetFrameworks>netstandard2.0</CompatibilityTargetFrameworks>
<DefaultTargetFrameworks>net7.0;net8.0</DefaultTargetFrameworks>
<DefaultTargetFrameworks>net7.0;net8.0;net9.0;</DefaultTargetFrameworks>
<LangVersion>preview</LangVersion>
</PropertyGroup>

Expand Down
7 changes: 7 additions & 0 deletions Microsoft.Azure.CosmosRepository.sln
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventSourcingCustomerAccoun
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.CosmosEventSourcingAcceptanceTests", "tests\Microsoft.Azure.CosmosEventSourcingAcceptanceTests\Microsoft.Azure.CosmosEventSourcingAcceptanceTests.csproj", "{99ADC0F0-9433-49AD-86FA-34009CD293BA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BugSandbox", "samples\Microsoft.Azure.CosmosRepository\BugSandbox\BugSandbox.csproj", "{7354577A-699D-4952-B8DF-27CF0FC7F683}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -180,6 +182,10 @@ Global
{99ADC0F0-9433-49AD-86FA-34009CD293BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99ADC0F0-9433-49AD-86FA-34009CD293BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99ADC0F0-9433-49AD-86FA-34009CD293BA}.Release|Any CPU.Build.0 = Release|Any CPU
{7354577A-699D-4952-B8DF-27CF0FC7F683}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7354577A-699D-4952-B8DF-27CF0FC7F683}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7354577A-699D-4952-B8DF-27CF0FC7F683}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7354577A-699D-4952-B8DF-27CF0FC7F683}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -210,6 +216,7 @@ Global
{D276C752-4DB7-4380-AF76-91492E8F8554} = {8F8738AD-EBC3-4C24-882B-5D9FAC427E80}
{7A2873BC-70A1-489B-9609-E9D7D382C826} = {8F8738AD-EBC3-4C24-882B-5D9FAC427E80}
{99ADC0F0-9433-49AD-86FA-34009CD293BA} = {F8ED6752-5ED3-4EA1-89F0-363C40F8D8E0}
{7354577A-699D-4952-B8DF-27CF0FC7F683} = {2EEE3D0D-6457-46D8-B8E8-FA7364942F1F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6AAE7641-B62C-48BA-8FE6-0F819E5B45EF}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace EventSourcingJobsTracker.Core.Aggregates;

public class JobsList : AggregateRoot
{
private readonly List<Job> _jobs = new();
private readonly List<Job> _jobs = [];

public Guid Id { get; private set; }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.Azure.CosmosRepository\Microsoft.Azure.CosmosRepository.csproj" />
</ItemGroup>

</Project>
67 changes: 67 additions & 0 deletions samples/Microsoft.Azure.CosmosRepository/BugSandbox/Program.cs

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgive me. I am still learning how to test this myself.
Since this is a sample, we can prove that the changes are working using the logged query.
If I wanted to turn this into a Test, all I would need to do is make a second repository with the same container and use a different model for seeding, right?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I manually verified it, and watched the logs correctly produce the expected result. I should have written a test, but this was easier - and I was short on time.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License.

using Microsoft.Azure.CosmosRepository;
using Microsoft.Azure.CosmosRepository.Specification;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

// https://learn.microsoft.com/azure/cosmos-db/how-to-develop-emulator?tabs=docker-linux%2Ccsharp&pivots=api-nosql
const string EmulatorConnectionString = """
AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;
""";

var builder = Host.CreateApplicationBuilder(args);

ServiceProvider provider = builder.Services.AddCosmosRepository(options =>
{
options.CosmosConnectionString = EmulatorConnectionString;
options.DatabaseId = "bug-sandbox";
options.ContainerBuilder.Configure<ExampleModel>(
static containerOptions => containerOptions
.WithoutStrictTypeChecking()
.WithContainer("Example")
.WithPartitionKey("/id"));
})
.BuildServiceProvider();

IRepository<ExampleModel> repository = provider.GetRequiredService<IRepository<ExampleModel>>();

await SeedAsync();

var queryResult = await repository.QueryAsync(new ExampleSpecification());

if (queryResult is { })
{
// Noice!
}

async Task SeedAsync()
{
IEnumerable<ExampleModel> current = await repository.GetAsync(x => x.Type == nameof(ExampleModel));

if (current.Any())
{
return;
}

await repository.CreateAsync(
[
new() { Category = "Red" },
new() { Category = "Yellow" },
new() { Category = "Blue" },
new() { Category = "Orange" },
new() { Category = "Green" },
]);
}

public class ExampleModel : Item
{
public string Category { get; set; }
}

public class ExampleSpecification : DefaultSpecification<ExampleModel>
{
public ExampleSpecification() =>
Query.Where(q => q.Category == "Red");
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,9 @@

namespace Specification;

public class FullSpecificationSamples
public class FullSpecificationSamples(IRepository<Person> repository)
{
private readonly IRepository<Person> _repository;

public FullSpecificationSamples(IRepository<Person> repository)
{
_repository = repository;
}
private readonly IRepository<Person> _repository = repository;

public async Task FullContinuationTokenSpecificationAsync(int age)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,38 @@
SpecificationPagingSamples pagingExamples = new(repository);

Console.WriteLine("Specification paging");

await pagingExamples.BasicPageAsync();

Console.WriteLine("Specification continuation token");

await pagingExamples.BasicScrollingAsync();

SpecificationOrderSamples orderSamples = new(repository);

Console.WriteLine("Simple ordering");

await orderSamples.BasicOrderAsync();

Console.WriteLine("Multiple fields ordering");

//This requires a composite index with name desc then age to work
await orderSamples.MultipleOrderByAsync();

SpecificationFilterSamples filterSamples = new(repository);

Console.WriteLine("Simple filtering");

await filterSamples.FilterSamples();

FullSpecificationSamples fullSpecificationSamples = new(repository);

Console.WriteLine("Continuation Token with query sample");

await fullSpecificationSamples.FullContinuationTokenSpecificationAsync(10);

Console.WriteLine("Offset by page number query sample");

await fullSpecificationSamples.FullPageNumberSpecificationAsync(10);

async Task SeedAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,12 @@

namespace Specification;

public class SpecificationOrderSamples
public class SpecificationOrderSamples(IRepository<Person> repository)
{
private readonly IRepository<Person> _repository;

public SpecificationOrderSamples(IRepository<Person> repository)
{
_repository = repository;
}
public async Task BasicOrderAsync()
{
OrderByNameSpecification specification = new();
IQueryResult<Person> result = await _repository.QueryAsync(specification);
IQueryResult<Person> result = await repository.QueryAsync(specification);

Console.WriteLine($"Simple order first result {result.Items[0].Name}");
Console.WriteLine($"Total Charge {result.Charge} RU's");
Expand All @@ -43,7 +37,7 @@ public async Task BasicOrderAsync()
public async Task MultipleOrderByAsync()
{
OrderByMultipleFieldsSpecification specification = new();
IQueryResult<Person> result = await _repository.QueryAsync(specification);
IQueryResult<Person> result = await repository.QueryAsync(specification);

Console.WriteLine($"Multiple order first result {result.Items[0].Name}");
Console.WriteLine($"Total Charge {result.Charge} RU's");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,8 @@

namespace Specification;

public class SpecificationPagingSamples
public class SpecificationPagingSamples(IRepository<Person> repository)
{
private readonly IRepository<Person> _repository;

public SpecificationPagingSamples(IRepository<Person> repository)
{
_repository = repository;
}
public async Task BasicPageAsync()
{
double totalCharge = 0;
Expand All @@ -28,7 +22,7 @@ public async Task BasicPageAsync()
}
totalCharge += page.Charge;
specification.NextPage();
page = await _repository.QueryAsync(specification);
page = await repository.QueryAsync(specification);
Console.WriteLine($"Get page {page.PageNumber} 25 results cost {page.Charge}");
}
Console.WriteLine($"Total Charge {totalCharge} RU's");
Expand All @@ -40,7 +34,7 @@ public async Task BasicScrollingAsync()
double totalCharge = 0;

ContinuationTokenSpecification<Person> specification = new(null, pageSize: 25);
IPage<Person> page = await _repository.QueryAsync(specification);
IPage<Person> page = await repository.QueryAsync(specification);
specification.UpdateContinuationToken(page.Continuation);
var totalItems = 0;
while (totalItems < page.Total)
Expand All @@ -53,7 +47,7 @@ public async Task BasicScrollingAsync()
totalCharge += page.Charge;
Console.WriteLine($"First 25 results cost {page.Charge}");
specification.UpdateContinuationToken(page.Continuation);
page = await _repository.QueryAsync(specification);
page = await repository.QueryAsync(specification);
}

Console.WriteLine($"Last 50 results cost {page.Charge}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,19 @@

namespace Specification;

public class SpecificationFilterSamples
public class SpecificationFilterSamples(IRepository<Person> repository)
{
private readonly IRepository<Person> _repository;

public SpecificationFilterSamples(IRepository<Person> repository)
{
_repository = repository;
}

public async Task FilterSamples()
{
AllPersonsWithNameSpecification nameSpecification = new("Tom");
IQueryResult<Person> personsWithNameTom = await _repository.QueryAsync(nameSpecification);
IQueryResult<Person> personsWithNameTom = await repository.QueryAsync(nameSpecification);

Console.WriteLine($"Found {personsWithNameTom.Items.Count} with name Tom");
Console.WriteLine($"Change for query {personsWithNameTom.Charge}");

var age = 25;
AllPersonsOlderThanSpecifciation ageSpecification = new(age);
IQueryResult<Person> peopleOlderThan25 = await _repository.QueryAsync(ageSpecification);
AllPersonsOlderThanSpecification ageSpecification = new(age);
IQueryResult<Person> peopleOlderThan25 = await repository.QueryAsync(ageSpecification);

Console.WriteLine($"Found {peopleOlderThan25.Items.Count} people older than {age}");
Console.WriteLine($"Change for query {peopleOlderThan25.Charge}");
Expand All @@ -39,9 +32,9 @@ public AllPersonsWithNameSpecification(string name)
}
}

private class AllPersonsOlderThanSpecifciation : DefaultSpecification<Person>
private class AllPersonsOlderThanSpecification : DefaultSpecification<Person>
{
public AllPersonsOlderThanSpecifciation(int age)
public AllPersonsOlderThanSpecification(int age)
{
Query.Where(p => p.Age > age);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ public async Task Post_Always_Creates_A_Language()
InitialReleaseDate = new DateTime(2001, 10, 25)
};

List<LanguageDto> languages = new()
{
List<LanguageDto> languages =
[
language
};
];

IRepository<Language> repository = _repositoryFactory.RepositoryOf<Language>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace Microsoft.Azure.CosmosEventSourcing.Aggregates;
/// <inheritdoc />
public abstract class AggregateRoot : IAggregateRoot
{
private List<DomainEvent> _events = new();
private readonly List<DomainEvent> _newEvents = new();
private List<DomainEvent> _events = [];
private readonly List<DomainEvent> _newEvents = [];
private AtomicEvent? _atomicEvent;

/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Microsoft.Azure.CosmosEventSourcing.Converters;

internal class DomainEventConverter : JsonConverter
{
public static HashSet<Type> ConvertableTypes { get; } = new();
public static HashSet<Type> ConvertableTypes { get; } = [];

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) =>
serializer.Serialize(writer, value, value.GetType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ private class ParameterReBinder : ExpressionVisitor
private readonly Dictionary<ParameterExpression, ParameterExpression> _map;

private ParameterReBinder(Dictionary<ParameterExpression, ParameterExpression> map) =>
_map = map ?? new();
_map = map ?? [];

internal static Expression ReplaceParameters(
Dictionary<ParameterExpression, ParameterExpression> map, Expression exp) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Microsoft.Azure.CosmosRepository.Builders;
/// <inheritdoc/>
internal class DefaultItemContainerBuilder : IItemContainerBuilder
{
private readonly List<ContainerOptionsBuilder> _options = new();
private readonly List<ContainerOptionsBuilder> _options = [];

public IReadOnlyList<ContainerOptionsBuilder> Options => _options;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ namespace Microsoft.Azure.CosmosRepository.Builders;

internal class PatchOperationBuilder<TItem> : IPatchOperationBuilder<TItem> where TItem : IItem
{
private readonly List<PatchOperation> _patchOperations = new();
private readonly List<PatchOperation> _patchOperations = [];
private readonly NamingStrategy _namingStrategy;

internal readonly List<InternalPatchOperation> _rawPatchOperations = new();
internal readonly List<InternalPatchOperation> _rawPatchOperations = [];

public IReadOnlyList<PatchOperation> PatchOperations => _patchOperations;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal class ParameterRebinder : ExpressionVisitor
readonly Dictionary<ParameterExpression, ParameterExpression> _map;

internal ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map) =>
_map = map ?? new();
_map = map ?? [];

internal static Expression ReplaceParameters(
Dictionary<ParameterExpression, ParameterExpression> map, Expression exp) =>
Expand Down

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank You, This cleanly resolves #452

Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ public Expression<Func<TItem, bool>> Build<TItem>(Expression<Func<TItem, bool>>
return options.UseStrictTypeChecking ? predicate.Compose(Default<TItem>(), Expression.AndAlso) : predicate;
}

public Expression<Func<TItem, bool>> Default<TItem>() where TItem : IItem =>
item => !item.Type.IsDefined() || item.Type == typeof(TItem).Name;
public Expression<Func<TItem, bool>> Default<TItem>() where TItem : IItem
{
ItemConfiguration options = itemConfigurationProvider.GetItemConfiguration<TItem>();

return options.UseStrictTypeChecking
? item => !item.Type.IsDefined() || item.Type == typeof(TItem).Name
: item => item != null /* If strict typing isn't desired, the default is a simple not null check */;
}

public TItem CheckItem<TItem>(TItem item) where TItem : IItem
{
Expand Down
Loading