From 083412403450fcfa52dea163b916a576b6dc571d Mon Sep 17 00:00:00 2001 From: Maxim Voronov Date: Sun, 3 Feb 2019 12:55:53 +0300 Subject: [PATCH] add support filter segment --- .../Cache/UriCompare/ODataPathComparer.cs | 4 ++ .../OeCacheComparerParameterValues.cs | 10 +++-- source/OdataToEntity/Parsers/OeGetParser.cs | 2 - .../Parsers/OeParseNavigationSegment.cs | 41 +++++++++++-------- .../Parsers/Translators/OeSelectItem.cs | 3 ++ test/OdataToEntity.Test/Common/SelectTest.cs | 13 ++++++ test/OdataToEntity.Test/Common/SelectTest2.cs | 6 ++- 7 files changed, 55 insertions(+), 24 deletions(-) diff --git a/source/OdataToEntity/Parsers/Cache/UriCompare/ODataPathComparer.cs b/source/OdataToEntity/Parsers/Cache/UriCompare/ODataPathComparer.cs index 1f98258..2af97ed 100644 --- a/source/OdataToEntity/Parsers/Cache/UriCompare/ODataPathComparer.cs +++ b/source/OdataToEntity/Parsers/Cache/UriCompare/ODataPathComparer.cs @@ -49,6 +49,10 @@ public override bool Translate(EntitySetSegment segment) { return GetNextSegment() is EntitySetSegment entitySetSegment && entitySetSegment.EntitySet == segment.EntitySet; } + public override bool Translate(FilterSegment segment) + { + return GetNextSegment() is FilterSegment filterSegment && filterSegment.EdmType == segment.EdmType; + } public override bool Translate(KeySegment segment) { if (GetNextSegment() is KeySegment keySegment && keySegment.EdmType == segment.EdmType && keySegment.NavigationSource == segment.NavigationSource) diff --git a/source/OdataToEntity/Parsers/Cache/UriCompare/OeCacheComparerParameterValues.cs b/source/OdataToEntity/Parsers/Cache/UriCompare/OeCacheComparerParameterValues.cs index 227ffcc..0195f61 100644 --- a/source/OdataToEntity/Parsers/Cache/UriCompare/OeCacheComparerParameterValues.cs +++ b/source/OdataToEntity/Parsers/Cache/UriCompare/OeCacheComparerParameterValues.cs @@ -110,10 +110,10 @@ private static String GetSegmentResourcePath(ODataPath path, String skipOrTop) if (stringBuilder.Length > 0) stringBuilder.Append('/'); - if (pathSegment is EntitySetSegment) - stringBuilder.Append((pathSegment as EntitySetSegment).EntitySet.Name); - else if (pathSegment is NavigationPropertySegment) - stringBuilder.Append((pathSegment as NavigationPropertySegment).NavigationProperty.Name); + if (pathSegment is EntitySetSegment entitySetSegment) + stringBuilder.Append(entitySetSegment.EntitySet.Name); + else if (pathSegment is NavigationPropertySegment navigationPropertySegment) + stringBuilder.Append(navigationPropertySegment.NavigationProperty.Name); else if (pathSegment is KeySegment) { stringBuilder.Append(pathSegment.Identifier); @@ -121,6 +121,8 @@ private static String GetSegmentResourcePath(ODataPath path, String skipOrTop) } else if (pathSegment is CountSegment) stringBuilder.Append(pathSegment.Identifier); + else if (pathSegment is FilterSegment) + stringBuilder.Append(pathSegment.Identifier); else throw new InvalidOperationException("unknown ODataPathSegment " + pathSegment.GetType().ToString()); } diff --git a/source/OdataToEntity/Parsers/OeGetParser.cs b/source/OdataToEntity/Parsers/OeGetParser.cs index 770442e..c20ec7d 100644 --- a/source/OdataToEntity/Parsers/OeGetParser.cs +++ b/source/OdataToEntity/Parsers/OeGetParser.cs @@ -5,8 +5,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; -using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; diff --git a/source/OdataToEntity/Parsers/OeParseNavigationSegment.cs b/source/OdataToEntity/Parsers/OeParseNavigationSegment.cs index 634a63e..118ac9c 100644 --- a/source/OdataToEntity/Parsers/OeParseNavigationSegment.cs +++ b/source/OdataToEntity/Parsers/OeParseNavigationSegment.cs @@ -35,6 +35,22 @@ public static IEdmEntitySet GetEntitySet(IReadOnlyList return null; } + private static NavigationPropertySegment GetNavigationSegment(ODataPathSegment previousSegment, out IEdmEntitySet entitySet) + { + if (previousSegment is EntitySetSegment entitySetSegment) + { + entitySet = entitySetSegment.EntitySet; + return null; + } + + if (previousSegment is NavigationPropertySegment navigationPropertySegment) + { + entitySet = (IEdmEntitySet)navigationPropertySegment.NavigationSource; + return navigationPropertySegment; + } + + throw new InvalidOperationException("Invalid segment"); + } public static IReadOnlyList GetNavigationSegments(ODataPath path) { var navigationSegments = new List(); @@ -46,24 +62,17 @@ public static IReadOnlyList GetNavigationSegments(ODat navigationSegments.Add(new OeParseNavigationSegment(navigationSegment, null)); else if (segment is KeySegment keySegment) { - IEdmEntitySet previousEntitySet; - navigationSegment = null; - if (previousSegment is EntitySetSegment) - { - var previousEntitySetSegment = previousSegment as EntitySetSegment; - previousEntitySet = previousEntitySetSegment.EntitySet; - } - else if (previousSegment is NavigationPropertySegment) - { - navigationSegment = previousSegment as NavigationPropertySegment; - previousEntitySet = (IEdmEntitySet)navigationSegment.NavigationSource; - } - else - throw new InvalidOperationException("invalid segment"); - - FilterClause keyFilter = CreateFilterClause(previousEntitySet, keySegment.Keys); + navigationSegment = GetNavigationSegment(previousSegment, out IEdmEntitySet entitySet); + FilterClause keyFilter = CreateFilterClause(entitySet, keySegment.Keys); navigationSegments.Add(new OeParseNavigationSegment(navigationSegment, keyFilter)); } + else if (segment is FilterSegment filterSegment) + { + navigationSegment = GetNavigationSegment(previousSegment, out _); + FilterClause filterClause = new FilterClause(filterSegment.Expression, filterSegment.RangeVariable); + navigationSegments.Add(new OeParseNavigationSegment(navigationSegment, filterClause)); + } + previousSegment = segment; } diff --git a/source/OdataToEntity/Parsers/Translators/OeSelectItem.cs b/source/OdataToEntity/Parsers/Translators/OeSelectItem.cs index 9f03645..253a94c 100644 --- a/source/OdataToEntity/Parsers/Translators/OeSelectItem.cs +++ b/source/OdataToEntity/Parsers/Translators/OeSelectItem.cs @@ -99,6 +99,9 @@ private static IEdmEntitySet GetEntitySet(ODataPath path) if (path.LastSegment is OperationSegment) return ((EntitySetSegment)path.FirstSegment).EntitySet; + if (path.LastSegment is FilterSegment) + return ((EntitySetSegment)path.FirstSegment).EntitySet; + throw new InvalidOperationException("unknown segment type " + path.LastSegment.ToString()); } public IReadOnlyList GetJoinPath() diff --git a/test/OdataToEntity.Test/Common/SelectTest.cs b/test/OdataToEntity.Test/Common/SelectTest.cs index a5f23d6..c8de4b7 100644 --- a/test/OdataToEntity.Test/Common/SelectTest.cs +++ b/test/OdataToEntity.Test/Common/SelectTest.cs @@ -886,6 +886,19 @@ public async Task FilterNavigation(int pageSize) [Theory] [InlineData(0)] [InlineData(1)] + public async Task FilterSegment(int pageSize) + { + var parameters = new QueryParameters() + { + RequestUri = "Customers/$filter(Sex eq OdataToEntity.Test.Model.Sex'Female')?$orderby=Id", + Expression = t => t.Where(c => c.Sex == Sex.Female).OrderBy(c => c.Id), + PageSize = pageSize + }; + await Fixture.Execute(parameters).ConfigureAwait(false); + } + [Theory] + [InlineData(0)] + [InlineData(1)] public async Task FilterStringConcat(int pageSize) { var parameters = new QueryParameters() diff --git a/test/OdataToEntity.Test/Common/SelectTest2.cs b/test/OdataToEntity.Test/Common/SelectTest2.cs index 0f19cf4..63ad1ec 100644 --- a/test/OdataToEntity.Test/Common/SelectTest2.cs +++ b/test/OdataToEntity.Test/Common/SelectTest2.cs @@ -18,10 +18,12 @@ public async Task BoundFunctionCollection() { List expectedResult; using (var dbContext = Fixture.CreateContext()) - expectedResult = dbContext.OrderItems.Where(i => i.Order.Name == "Order 1" || i.Order.Name == "Order 2").Select(i => i.Id).ToList(); + expectedResult = dbContext.OrderItems.Where(i => + (i.Order.Name == "Order 1" || i.Order.Name == "Order 2") && i.Order.Customer.Sex == Model.Sex.Female) + .Select(i => i.Id).ToList(); Db.OeDataAdapter dataAdapter = Fixture.EdmModel.GetDataAdapter(Fixture.EdmModel.EntityContainer); - String request = $"Customers/BoundFunctionCollection(orderNames=['Order 1','Order 2'])?$expand=Customer,Items&$select=Name"; + String request = $"Customers/$filter(Sex eq 'Female')/BoundFunctionCollection(orderNames=['Order 1','Order 2'])?$expand=Customer,Items&$select=Name"; ODataUri odataUri = Fixture.ParseUri(request); IEdmModel edmModel = Fixture.EdmModel.GetEdmModel(odataUri.Path);