diff --git a/samples/TableClient.DependencyInjection.AdvancedSample/SampleConsole.cs b/samples/TableClient.DependencyInjection.AdvancedSample/SampleConsole.cs index 71d32b8..d2ca740 100644 --- a/samples/TableClient.DependencyInjection.AdvancedSample/SampleConsole.cs +++ b/samples/TableClient.DependencyInjection.AdvancedSample/SampleConsole.cs @@ -46,7 +46,7 @@ public async Task Run() await foreach (var batch in _projectionClient.GetAsync(p => p - .WithTags() + .IncludeTags() .WherePartitionKey() .GreaterThanOrEqual("~"))) { diff --git a/samples/TableClient.DependencyInjection.ProjectionSample/SampleConsole.cs b/samples/TableClient.DependencyInjection.ProjectionSample/SampleConsole.cs index ce419bc..bfe1f95 100644 --- a/samples/TableClient.DependencyInjection.ProjectionSample/SampleConsole.cs +++ b/samples/TableClient.DependencyInjection.ProjectionSample/SampleConsole.cs @@ -1,5 +1,4 @@ -using Azure.EntityServices.Queries; -using Azure.EntityServices.Tables; +using Azure.EntityServices.Tables; using Common.Samples.Models; using Common.Samples.Tools.Fakes; using Microsoft.Extensions.Azure; @@ -25,7 +24,6 @@ public SampleConsole(IAzureClientFactory> entit { _entityClient = entityClientFactory.CreateClient("Source"); _projectionClient = entityClientFactory.CreateClient("Projection"); - } public async Task Run() @@ -43,20 +41,17 @@ public async Task Run() await _entityClient.AddOrReplaceManyAsync(persons); var count = 0; - await foreach (var result in _entityClient + await foreach (var result in _entityClient .GetAsync(filter => filter - .WhereTag("LastName") - .GreaterThan(""))) + .WithTag(p => p.LastName))) + { - foreach (var person in result) - { - Console.WriteLine(person.LastName); + { + Console.WriteLine(person.LastName); } count += result.Count(); await _projectionClient.AddOrReplaceManyAsync(result); - - } Console.WriteLine($"updated projection entities: {count}"); Console.WriteLine("===================================="); diff --git a/src/Azure.EntityServices.Tables/Queries/TableQueryExtensions.cs b/src/Azure.EntityServices.Tables/Queries/TableQueryExtensions.cs index 4bcf5db..f79bd85 100644 --- a/src/Azure.EntityServices.Tables/Queries/TableQueryExtensions.cs +++ b/src/Azure.EntityServices.Tables/Queries/TableQueryExtensions.cs @@ -8,14 +8,7 @@ namespace Azure.EntityServices.Tables /// public static class TableQueryExtensions { - public static IFilterOperator IgnoreTags(this IQuery query) - - => (query as IQueryCompose) - .AddQuery("PartitionKey") - .LessThan("~") - .AndRowKey() - .LessThan("~"); - + public static IQueryFilter WherePartitionKey(this IQuery query) => (query as IQueryCompose).AddQuery("PartitionKey"); diff --git a/src/Azure.EntityServices.Tables/Queries/TableTagQueryExtensions.cs b/src/Azure.EntityServices.Tables/Queries/TableTagQueryExtensions.cs index 63e08fd..371078c 100644 --- a/src/Azure.EntityServices.Tables/Queries/TableTagQueryExtensions.cs +++ b/src/Azure.EntityServices.Tables/Queries/TableTagQueryExtensions.cs @@ -10,15 +10,77 @@ namespace Azure.EntityServices.Tables /// public static class TableTagQueryExtensions { + public static IFilterOperator IgnoreTags(this IQuery query) + + => (query as IQueryCompose) + .AddQuery("PartitionKey") + .LessThan("~") + .AndRowKey() + .LessThan("~"); + /// - /// Use this extension to show all entities of a table including tagged partitions and rows + /// Use this extension to include tagged entities (replicated partitions and rows) /// - public static IQuery WithTags(this IQuery query) + public static IQuery IncludeTags(this IQuery query) { (query as ITagQueryCompose).TagName = " "; + return query; } + /// + /// Filter only tagged partitions and rows + /// + /// + /// + /// + public static IFilterOperator WithOnlyTags(this IQuery query) + + { + (query as ITagQueryCompose).TagName = " "; + return (query as IQueryCompose) + .AddQuery("PartitionKey") + .GreaterThan("~") + .AndRowKey() + .GreaterThan("~"); + } + + /// + /// Allow to retrieve all entities for a given tag + /// + /// + /// + /// + /// + public static IFilterOperator WithTag(this IQuery query, string tagName) + { + (query as ITagQueryCompose).TagName = " "; + return query + .WhereRowKey() + .GreaterThan($"~{tagName}-") + .AndRowKey() + .LessThan($"~{tagName}-~"); + } + + /// + /// Allow to retrieve all entities for a given tag as property selector + /// + /// + /// + /// + /// + /// + public static IFilterOperator WithTag(this IQuery query, Expression> tagSelector) + { + var tagName = tagSelector.GetPropertyInfo().Name; + (query as ITagQueryCompose).TagName = " "; + return query + .WhereRowKey() + .GreaterThan($"~{tagName}-") + .AndRowKey() + .LessThan($"~{tagName}-~"); + } + public static ITagQueryFilter WhereTag(this IQuery query, string tagName) { (query as ITagQueryCompose).TagName = tagName; diff --git a/tests/Azure.EntityServices.Tests/QueryExpressions/TableStorageQueryBuilderTests.cs b/tests/Azure.EntityServices.Tests/QueryExpressions/TableStorageQueryBuilderTests.cs index 23ac61a..2d62a3d 100644 --- a/tests/Azure.EntityServices.Tests/QueryExpressions/TableStorageQueryBuilderTests.cs +++ b/tests/Azure.EntityServices.Tests/QueryExpressions/TableStorageQueryBuilderTests.cs @@ -1,7 +1,7 @@ using Azure.EntityServices.Queries; -using Common.Samples.Models; using Azure.EntityServices.Tables; using Azure.EntityServices.Tables.Core; +using Common.Samples.Models; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; @@ -154,6 +154,7 @@ public void Should_Build_Table_Filter_Expression_With_Invariant_Floating_Point_V result.Should() .Be("PartitionKey eq 'tenantId' and Latitude eq 48.77309806265856 and Distance eq '148.45648566856' and BankAmount eq '1248.7731'"); } + [TestMethod] public void Should_Use_Multi_PartitionKey_filter() { @@ -166,14 +167,43 @@ public void Should_Use_Multi_PartitionKey_filter() .Equal("partition2") .OrPartitionKey() .Equal("Partition3"); - + var queryStr = builder.Build(); queryStr.Trim() .Should() .Be("PartitionKey eq 'partition1' or PartitionKey eq 'partition2' or PartitionKey eq 'Partition3'"); + } + + [TestMethod] + public void Should_Use_WithTag_Extension_To_Get_All_Tag_Values_Without_Filter_Operator() + { + var builder = new TableStorageQueryBuilder(new TagFilterExpression()); + + (builder.Query as TagFilterExpression) + .WithTag("Created") + .And(p => p.TenantId).Equal("10"); + var queryStr = builder.Build(); + + queryStr.Trim() + .Should() + .Be("RowKey gt '~Created-' and RowKey lt '~Created-~' and TenantId eq '10'"); + } + + [TestMethod] + public void Should_Use_IncludeTags_To_Get_All_Entities_Included_All_Tags() + { + var builder = new TableStorageQueryBuilder(new TagFilterExpression()); - } - + (builder.Query as TagFilterExpression) + .IncludeTags() + .WherePartitionKey().Equal("tenant1"); + + var queryStr = builder.Build(); + + queryStr.Trim() + .Should() + .Be("PartitionKey eq 'tenant1'"); + } } } \ No newline at end of file