Skip to content

Commit

Permalink
bugfix: ToDictionary works wrong with nested queries #89, Is resource…
Browse files Browse the repository at this point in the history
… parameter necessary in ODataQueryBuilder.For<TEntity> #88 (#91)

* bugfix: ToDictionary works wrong with nested queries #89
* Is resource parameter necessary in ODataQueryBuilder.For<TEntity> #88
  • Loading branch information
ZEXSM authored Feb 12, 2022
1 parent f791f30 commit 5c72a1e
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ internal class ODataQuery : IODataQuery
protected readonly ODataQueryBuilderOptions _odataQueryBuilderOptions;
protected readonly StringBuilder _stringBuilder;

private static readonly char[] SeparatorUri = new char[2] { QuerySeparators.Begin, QuerySeparators.Main };
private static readonly char[] SeparatorOperator = new char[1] { QuerySeparators.EqualSign };

public ODataQuery(StringBuilder stringBuilder, ODataQueryBuilderOptions odataQueryBuilderOptions)
{
_stringBuilder = stringBuilder;
Expand All @@ -20,16 +23,21 @@ public ODataQuery(StringBuilder stringBuilder, ODataQueryBuilderOptions odataQue

public IDictionary<string, string> ToDictionary()
{
var odataOperators = _stringBuilder.ToString()
.Split(new char[2] { QuerySeparators.Begin, QuerySeparators.Main }, StringSplitOptions.RemoveEmptyEntries);
var odataOperators = _stringBuilder
.ToString()
.Split(SeparatorUri, StringSplitOptions.RemoveEmptyEntries);

var dictionary = new Dictionary<string, string>(odataOperators.Length - 1);
var dictionary = new Dictionary<string, string>(odataOperators.Length);

for (var step = 1; step < odataOperators.Length; step++)
for (var step = 0; step < odataOperators.Length; step++)
{
var odataOperator = odataOperators[step].Split(QuerySeparators.EqualSign);
var odataOperator = odataOperators[step]
.Split(SeparatorOperator, 2, StringSplitOptions.RemoveEmptyEntries);

dictionary.Add(odataOperator[0], odataOperator[1]);
if (odataOperator.Length > 1)
{
dictionary.Add(odataOperator[0], odataOperator[1]);
}
}

return dictionary;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ public ODataResource(StringBuilder stringBuilder, ODataQueryBuilderOptions odata

public IAddressingEntries<TEntity> For<TEntity>(string resource)
{
if (string.IsNullOrWhiteSpace(resource))
if (resource == null)
{
throw new ArgumentException($"The specified resource name is null or empty", nameof(resource));
throw new ArgumentNullException(nameof(resource),"Resource name is null");
}

_stringBuilder.Append(resource);
if (resource != string.Empty)
{
_stringBuilder.Append(resource);
}

return new AddressingEntries<TEntity>(_stringBuilder, _odataQueryBuilderOptions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public IAddressingEntries<TEntity> For<TEntity>(Expression<Func<TResource, objec
{
if (resource == null)
{
throw new ArgumentException($"The specified resource name is null", nameof(resource));
throw new ArgumentNullException(nameof(resource), "Resource name is null");
}

var query = new ODataResourceExpressionVisitor().ToQuery(resource.Body);
Expand Down
89 changes: 76 additions & 13 deletions test/OData.QueryBuilder.Test/ODataQueryCollectionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1058,15 +1058,15 @@ public void ODataQueryBuilderList_ToDicionary()
var newObject = new ODataTypeEntity { IsOpen = false };

var dictionary = _odataQueryBuilderDefault
.For<ODataTypeEntity>(s => s.ODataType)
.ByList()
.Filter(s => s.IsActive
&& s.IsOpen == constValue
&& s.IsOpen == true
&& s.ODataKind.ODataCode.IdActive == newObject.IsOpen)
.Skip(1)
.Top(10)
.ToDictionary();
.For<ODataTypeEntity>(s => s.ODataType)
.ByList()
.Filter(s => s.IsActive
&& s.IsOpen == constValue
&& s.IsOpen == true
&& s.ODataKind.ODataCode.IdActive == newObject.IsOpen)
.Skip(1)
.Top(10)
.ToDictionary();

var resultEquivalent = new Dictionary<string, string>
{
Expand All @@ -1078,6 +1078,69 @@ public void ODataQueryBuilderList_ToDicionary()
dictionary.Should().BeEquivalentTo(resultEquivalent);
}

[Fact(DisplayName = "ToDicionary empty resource => Success")]
public void ODataQueryBuilderList_ToDicionary_Empty_Resource()
{
var dictionary = new ODataQueryBuilder()
.For<ODataTypeEntity>(string.Empty)
.ByList()
.Expand(s => s.ODataKind)
.Filter(s => s.IsActive == true)
.Select(s => s.Open)
.Skip(1)
.Top(10)
.ToDictionary();

var resultEquivalent = new Dictionary<string, string>
{
{ "$expand", "ODataKind" },
{ "$filter", "IsActive eq true" },
{ "$select", "Open" },
{ "$skip", "1" },
{ "$top", "10" }
};

dictionary.Should().BeEquivalentTo(resultEquivalent);
}

[Fact(DisplayName = "ToDicionary Complex => Success")]
public void ODataQueryBuilderList_ToDicionary_Complex_Success()
{
var dictionary = _odataQueryBuilderDefault
.For<ODataTypeEntity>(s => s.ODataType)
.ByList()
.Expand(f =>
{
f.For<ODataKindEntity>(s => s.ODataKind)
.Expand(ff => ff
.For<ODataCodeEntity>(s => s.ODataCode)
.Select(s => s.IdCode));
f.For<ODataKindEntity>(s => s.ODataKindNew)
.Expand(ff => ff.ODataCode)
.Select(s => s.IdKind);
f.For<ODataKindEntity>(s => s.ODataKindNew)
.Select(s => s.IdKind);
})
.Filter(s => s.IdRule == 3)
.Select(s => new { s.IdType, s.Sum })
.OrderBy(s => s.IdRule)
.Skip(10)
.Top(10)
.ToDictionary();

var resultEquivalent = new Dictionary<string, string>
{
["$expand"] = "ODataKind($expand=ODataCode($select=IdCode)),ODataKindNew($expand=ODataCode;$select=IdKind),ODataKindNew($select=IdKind)",
["$filter"] = "IdRule eq 3",
["$select"] = "IdType,Sum",
["$orderby"] = "IdRule asc",
["$skip"] = "10",
["$top"] = "10"
};

dictionary.Should().BeEquivalentTo(resultEquivalent);
}

[Fact(DisplayName = "ToDicionary => Exception")]
public void ODataQueryBuilderList_ToDicionary_Exception()
{
Expand All @@ -1088,8 +1151,8 @@ public void ODataQueryBuilderList_ToDicionary_Exception()
.Filter(s => s.IsActive)
.ToDictionary())
.Should()
.Throw<ArgumentException>()
.WithMessage($"The specified resource name is null (Parameter 'resource')");
.Throw<ArgumentNullException>()
.WithMessage("Resource name is null (Parameter 'resource')");
}

[Fact(DisplayName = "ToDicionary => Exception 2")]
Expand All @@ -1102,8 +1165,8 @@ public void ODataQueryBuilderList_ToDicionary_Exception_2()
.Filter(s => s.IsActive)
.ToDictionary())
.Should()
.Throw<ArgumentException>()
.WithMessage($"The specified resource name is null or empty (Parameter 'resource')");
.Throw<ArgumentNullException>()
.WithMessage("Resource name is null (Parameter 'resource')");
}

[Fact(DisplayName = "Filter Enum => Success")]
Expand Down

0 comments on commit 5c72a1e

Please sign in to comment.