Skip to content
Open
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
27 changes: 17 additions & 10 deletions src/FakeXrmEasy.Core/Query/FetchXmlExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ private static QueryExpression ToQueryExpression(this XDocument xlDoc, IXrmFaked
int? pageNumber = xlDoc.ToPageNumber();
bool? returnTotalRecordCount = xlDoc.ToReturnTotalRecordCount();

bool hasPageInfoAttributes = count != null
|| pageNumber != null
bool hasPageInfoAttributes = count != null
|| pageNumber != null
|| returnTotalRecordCount != null;

query.PageInfo = null;
if(hasPageInfoAttributes)
if (hasPageInfoAttributes)
{
query.PageInfo = new PagingInfo();
query.PageInfo.Count = count ?? 0;
Expand Down Expand Up @@ -139,9 +139,7 @@ public static List<Entity> Aggregate(this List<Entity> resultOfQuery, XrmFakedCo
{
//TODO: Find entity alias. Handle aliasedvalue in the query result.
var namespacedAlias = attr.Ancestors(ns + "link-entity").Select(x => x.GetAttribute("alias")?.Value != null ? x.GetAttribute("alias").Value : x.GetAttribute("name").Value).ToList();
namespacedAlias.Add(attr.GetAttribute("alias")?.Value);
var alias = string.Join(".", namespacedAlias);
namespacedAlias.RemoveAt(namespacedAlias.Count - 1);
var alias = attr.GetAttribute("alias")?.Value;
namespacedAlias.Add(attr.GetAttribute("name")?.Value);
var logicalName = string.Join(".", namespacedAlias);

Expand Down Expand Up @@ -423,7 +421,7 @@ protected override object AggregateAliasedValues(IEnumerable<object> values)
{
return lst.Min(x => (double)x);
}

if (valType == typeof(DateTime) || valType == typeof(DateTime?))
{
return lst.Min(x => (DateTime)x);
Expand Down Expand Up @@ -467,7 +465,7 @@ protected override object AggregateAliasedValues(IEnumerable<object> values)
{
return lst.Max(x => (double)x);
}

if (valType == typeof(DateTime) || valType == typeof(DateTime?))
{
return lst.Max(x => (DateTime)x);
Expand Down Expand Up @@ -549,7 +547,7 @@ protected override object AggregateAliasedValues(IEnumerable<object> values)
{
return lst.Sum(x => x as double? ?? 0d);
}

throw new Exception("Unhndled property type '" + valType.FullName + "' in 'sum' aggregate");
}
}
Expand Down Expand Up @@ -631,10 +629,19 @@ private class SimpleValueGroup : FetchGrouping
{
public override IComparable FindGroupValue(object attributeValue)
{
if (attributeValue is AliasedValue aliasedValue)
{
attributeValue = aliasedValue.Value;
}

if (attributeValue is EntityReference)
{
return new ComparableEntityReference(attributeValue as EntityReference) as IComparable;
}
else if (attributeValue is OptionSetValue)
{
return ((OptionSetValue)attributeValue).Value as IComparable;
}
else
{
return attributeValue as IComparable;
Expand Down Expand Up @@ -694,5 +701,5 @@ public override IComparable FindGroupValue(object attributeValue)
}
}
}

}
69 changes: 69 additions & 0 deletions tests/FakeXrmEasy.Core.Tests/Issues/Issue48.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Crm;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using Xunit;

namespace FakeXrmEasy.Tests.Issues
{
// https://github.com/DynamicsValue/fake-xrm-easy/issues/48

public class Issue48 : FakeXrmEasyTestsBase
{
SalesOrder _salesOrder;
String fetchXML;
// setup
public Issue48()
{
_context.EnableProxyTypes(typeof(SalesOrder).Assembly);

_salesOrder = new SalesOrder() {Id = Guid.NewGuid(), Name = "O-12345" };

SalesOrderDetail salesOrderDetail1 = new SalesOrderDetail() {Id = Guid.NewGuid(), SalesOrderId = _salesOrder.ToEntityReference(), LineItemNumber = 1 };

_context.Initialize(new List<Entity> { _salesOrder, salesOrderDetail1 });

fetchXML = @"<fetch aggregate='true'>
<entity name='salesorderdetail'>
<attribute name='salesorderdetailid' alias='count' aggregate='count' />
<link-entity name='salesorder' to='salesorderid' from='salesorderid' alias='so' link-type='inner'>
<attribute name='name' alias='name' groupby='true' />
<order alias='name' />
</link-entity>
</entity>
</fetch>";
}


[Fact]
public void When_An_Aggregated_Query_Contains_Group_By_Attributes_These_Should_Be_Returned_In_The_Query_Results()
{
EntityCollection records = _service.RetrieveMultiple(new FetchExpression(fetchXML));

// The 'name' column of the rist record should be the same as the orders name column
Assert.Equal(_salesOrder.Name, (string)((AliasedValue)records.Entities[0]["name"]).Value);
}

[Fact]
public void When_An_Aggregated_Query_Contains_Group_By_On_Base_Attributes_These_Should_Be_Returned_In_The_Query_Results()
{
EntityCollection records = _service.RetrieveMultiple(new FetchExpression(@"<fetch aggregate='true'>
<entity name='salesorderdetail'>
<attribute name='salesorderdetailid' alias='count' aggregate='count' />
<attribute name='lineitemnumber' alias='lineitemnumber' groupby='true' />
</entity>
</fetch>"));

Assert.Equal(1, (int)((AliasedValue)records.Entities[0]["lineitemnumber"]).Value);
}

[Fact]
public void When_An_Aggregated_Query_Contains_Group_By_Attributes_The_Right_Aggregate_Values_Should_Be_Returned_In_The_Query_Results()
{
EntityCollection records = _service.RetrieveMultiple(new FetchExpression(fetchXML));

Assert.Equal(1, (int)((AliasedValue)records.Entities[0]["count"]).Value);
}
}
}
Loading