diff --git a/FakeXrmEasy.2013/Properties/AssemblyInfo.cs b/FakeXrmEasy.2013/Properties/AssemblyInfo.cs
index 3760e94c..28460eb6 100644
--- a/FakeXrmEasy.2013/Properties/AssemblyInfo.cs
+++ b/FakeXrmEasy.2013/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.8.1")]
-[assembly: AssemblyFileVersion("1.8.1")]
+[assembly: AssemblyVersion("1.8.2")]
+[assembly: AssemblyFileVersion("1.8.2")]
diff --git a/FakeXrmEasy.2015/FakeXrmEasy.2015.csproj b/FakeXrmEasy.2015/FakeXrmEasy.2015.csproj
index 13569b80..df466a07 100644
--- a/FakeXrmEasy.2015/FakeXrmEasy.2015.csproj
+++ b/FakeXrmEasy.2015/FakeXrmEasy.2015.csproj
@@ -18,7 +18,7 @@
full
false
bin\Debug\
- DEBUG;TRACE
+ TRACE;DEBUG;FAKE_XRM_EASY_2015
prompt
4
false
diff --git a/FakeXrmEasy.2015/Properties/AssemblyInfo.cs b/FakeXrmEasy.2015/Properties/AssemblyInfo.cs
index 27b0bd24..382ec22a 100644
--- a/FakeXrmEasy.2015/Properties/AssemblyInfo.cs
+++ b/FakeXrmEasy.2015/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.8.1.0")]
-[assembly: AssemblyFileVersion("1.8.1.0")]
+[assembly: AssemblyVersion("1.8.2.0")]
+[assembly: AssemblyFileVersion("1.8.2.0")]
diff --git a/FakeXrmEasy.Tests.2013/buildNugetPackages.bat b/FakeXrmEasy.Tests.2013/buildNugetPackages.bat
index ce106396..b53af215 100644
--- a/FakeXrmEasy.Tests.2013/buildNugetPackages.bat
+++ b/FakeXrmEasy.Tests.2013/buildNugetPackages.bat
@@ -1,5 +1,5 @@
copy ..\FakeXrmEasy.2013\bin\Debug\FakeXrmEasy.dll .\build\lib\net40
cd build
nuget pack FakeXrmEasy.2013.dll.nuspec
-nuget push FakeXrmEasy.2013.1.8.1.nupkg
+nuget push FakeXrmEasy.2013.1.8.2.nupkg
pause
\ No newline at end of file
diff --git a/FakeXrmEasy.Tests.2015/FakeXrmEasy.Tests.2015.csproj b/FakeXrmEasy.Tests.2015/FakeXrmEasy.Tests.2015.csproj
index 2fdabdaf..2a10fddf 100644
--- a/FakeXrmEasy.Tests.2015/FakeXrmEasy.Tests.2015.csproj
+++ b/FakeXrmEasy.Tests.2015/FakeXrmEasy.Tests.2015.csproj
@@ -23,7 +23,7 @@
full
false
bin\Debug\
- DEBUG;TRACE
+ TRACE;DEBUG;FAKE_XRM_EASY_2015
prompt
4
diff --git a/FakeXrmEasy.Tests.2015/build/FakeXrmEasy.2015.dll.nuspec b/FakeXrmEasy.Tests.2015/build/FakeXrmEasy.2015.dll.nuspec
index 748bc832..0ed98dc9 100644
--- a/FakeXrmEasy.Tests.2015/build/FakeXrmEasy.2015.dll.nuspec
+++ b/FakeXrmEasy.Tests.2015/build/FakeXrmEasy.2015.dll.nuspec
@@ -2,7 +2,7 @@
FakeXrmEasy.2015
- 1.8.1
+ 1.8.2
@jordimontana
@jordimontana
https://raw.githubusercontent.com/jordimontana82/fake-xrm-easy/master/LICENSE.md
@@ -10,7 +10,7 @@
true
Utilities to streamline unit testing in Dynamics CRM 2013 by faking the IOrganizationService using FakeItEasy and make it work against an In-Memory context.
- fixed Assembly Name
+ Fixed issues with joins / linked entities and filters across versions as a new EntityName property was introduced in ConditionExpression >= 2013
Copyright 2015
xrm dynamics crm 2013 unit testing mock mocking fake fakes
diff --git a/FakeXrmEasy.Tests.2015/buildNugetPackages.bat b/FakeXrmEasy.Tests.2015/buildNugetPackages.bat
index fda375a5..22288a06 100644
--- a/FakeXrmEasy.Tests.2015/buildNugetPackages.bat
+++ b/FakeXrmEasy.Tests.2015/buildNugetPackages.bat
@@ -1,5 +1,5 @@
copy ..\FakeXrmEasy.2015\bin\Debug\FakeXrmEasy.dll .\build\lib\net452
cd build
nuget pack FakeXrmEasy.2015.dll.nuspec
-nuget push FakeXrmEasy.2015.1.8.1.nupkg
+nuget push FakeXrmEasy.2015.1.8.2.nupkg
pause
\ No newline at end of file
diff --git a/FakeXrmEasy.Tests/FakeContextTests/LinqTests/EqualityWithDifferentDataTypesTests.cs b/FakeXrmEasy.Tests/FakeContextTests/LinqTests/EqualityWithDifferentDataTypesTests.cs
index 1aec5a59..02aab5b4 100644
--- a/FakeXrmEasy.Tests/FakeContextTests/LinqTests/EqualityWithDifferentDataTypesTests.cs
+++ b/FakeXrmEasy.Tests/FakeContextTests/LinqTests/EqualityWithDifferentDataTypesTests.cs
@@ -339,8 +339,9 @@ public void When_executing_a_linq_query_with_equals_between_2_activityparties_re
using (XrmServiceContext ctx = new XrmServiceContext(service))
{
var activities = (from pointer in ctx.CreateQuery()
- join party in ctx.CreateQuery() on pointer.Id equals party.ActivityId.Id
- where party.PartyId.Id == contactId
+ join party in ctx.CreateQuery() on pointer.ActivityId.Value equals party.ActivityId.Id
+ // from party in ctx.CreateQuery() //on pointer.ActivityId.Value equals party.ActivityId.Id
+ where party.PartyId.Id == contactId
select pointer).ToList();
Assert.True(activities.Count == 1);
diff --git a/FakeXrmEasy.Tests/FakeContextTests/LinqTests/FakeContextTestLinqQueries.cs b/FakeXrmEasy.Tests/FakeContextTests/LinqTests/FakeContextTestLinqQueries.cs
index 29fb7af6..99afdcad 100644
--- a/FakeXrmEasy.Tests/FakeContextTests/LinqTests/FakeContextTestLinqQueries.cs
+++ b/FakeXrmEasy.Tests/FakeContextTests/LinqTests/FakeContextTestLinqQueries.cs
@@ -833,5 +833,39 @@ public void When_doing_a_crm_linq_query_that_produces_a_filter_expression_plus_c
Assert.True(matches.Count == 2);
}
}
+
+ [Fact(DisplayName = "When_doing_a_join_with_filter_then_can_filter_by_the_joined_entity_attributes")]
+ public void When_doing_a_join_with_filter_then_can_filter_by_the_joined_entity_attributes()
+ {
+ //REVIEW: Different implementations of the ConditionExpression class in Microsoft.Xrm.Sdk (which has EntityName property for versions >= 2013)
+
+ var fakedContext = new XrmFakedContext();
+ fakedContext.ProxyTypesAssembly = Assembly.GetExecutingAssembly();
+
+ var contactId = Guid.NewGuid();
+ var accountId = Guid.NewGuid();
+ var accountId2 = Guid.NewGuid();
+
+ //Contact is related to first account, but because first account is not related to itself then the query must return 0 records
+ fakedContext.Initialize(new List() {
+ new Account() { Id = accountId, Name="Account1" },
+ new Account() { Id = accountId2, Name = "Account2" },
+ new Contact() { Id = contactId, ParentCustomerId = new EntityReference(Account.EntityLogicalName, accountId),
+ NumberOfChildren = 2, FirstName = "Contact" },
+ new Contact() {Id = Guid.NewGuid(), ParentCustomerId = new EntityReference(Account.EntityLogicalName, accountId2) }
+ });
+
+ var service = fakedContext.GetFakedOrganizationService();
+
+ using (XrmServiceContext ctx = new XrmServiceContext(service))
+ {
+ var matches = (from c in ctx.CreateQuery()
+ join account in ctx.CreateQuery() on c.ParentCustomerId.Id equals account.AccountId
+ where account.Name == "Account1"
+ select c).ToList();
+
+ Assert.True(matches.Count == 1);
+ }
+ }
}
}
diff --git a/FakeXrmEasy.Tests/FakeContextTests/TranslateQueryExpressionTests/FakeContextTestTranslateQueryExpression.cs b/FakeXrmEasy.Tests/FakeContextTests/TranslateQueryExpressionTests/FakeContextTestTranslateQueryExpression.cs
index 3779fb7d..f67f831e 100644
--- a/FakeXrmEasy.Tests/FakeContextTests/TranslateQueryExpressionTests/FakeContextTestTranslateQueryExpression.cs
+++ b/FakeXrmEasy.Tests/FakeContextTests/TranslateQueryExpressionTests/FakeContextTestTranslateQueryExpression.cs
@@ -310,8 +310,11 @@ public void When_executing_a_query_expression_with_all_attributes_all_of_them_ar
var firstContact = result.FirstOrDefault();
var lastContact = result.LastOrDefault();
- Assert.True(firstContact.Attributes.Count == 3 + 4); //Contact 1 (the extra four are the CreatedOn, ModifiedOn, CreatedBy, ModifiedBy attributes generated automatically
- Assert.True(lastContact.Attributes.Count == 3 + 4); //Contact 2
+ //Contact 1 attributes = 3 + 4 (the extra four are the CreatedOn, ModifiedOn, CreatedBy, ModifiedBy attributes generated automatically
+ //+ Attributes from the join(account) = 1 + 4 (the extra four are the CreatedOn, ModifiedOn, CreatedBy, ModifiedBy attributes generated automatically
+
+ Assert.True(firstContact.Attributes.Count == 3 + 1 + 4 * 2);
+ Assert.True(lastContact.Attributes.Count == 3 + 1 + 4 * 2); //Contact 2
}
[Fact]
@@ -342,6 +345,7 @@ public void When_executing_a_query_expression_without_columnset_no_attributes_ar
}
);
+ qe.ColumnSet = new ColumnSet(false);
var result = XrmFakedContext.TranslateQueryExpressionToLinq(context, qe);
Assert.True(result.Count() == 2);
diff --git a/FakeXrmEasy.Tests/build/FakeXrmEasy.dll.nuspec b/FakeXrmEasy.Tests/build/FakeXrmEasy.dll.nuspec
index e8d85e0f..9ffe52d2 100644
--- a/FakeXrmEasy.Tests/build/FakeXrmEasy.dll.nuspec
+++ b/FakeXrmEasy.Tests/build/FakeXrmEasy.dll.nuspec
@@ -2,7 +2,7 @@
FakeXrmEasy
- 1.8.1
+ 1.8.2
@jordimontana
@jordimontana
https://raw.githubusercontent.com/jordimontana82/fake-xrm-easy/master/LICENSE.md
@@ -10,8 +10,7 @@
true
Utilities to streamline unit testing in Dynamics CRM by faking the IOrganizationService using FakeItEasy and make it work against an In-Memory context.
- Added the ability to pass custom mocks to the context.
- Bug fix.
+ Fixed issues with joins / linked entities and filters across versions as a new EntityName property was introduced in ConditionExpression >= 2013
Copyright 2015
xrm dynamics crm unit testing mock mocking fake fakes
diff --git a/FakeXrmEasy.Tests/build/lib/net40/FakeXrmEasy.dll b/FakeXrmEasy.Tests/build/lib/net40/FakeXrmEasy.dll
index aa58a6b5..0c40105a 100644
Binary files a/FakeXrmEasy.Tests/build/lib/net40/FakeXrmEasy.dll and b/FakeXrmEasy.Tests/build/lib/net40/FakeXrmEasy.dll differ
diff --git a/FakeXrmEasy.Tests/buildNugetPackages.bat b/FakeXrmEasy.Tests/buildNugetPackages.bat
index 7d019175..a9024baf 100644
--- a/FakeXrmEasy.Tests/buildNugetPackages.bat
+++ b/FakeXrmEasy.Tests/buildNugetPackages.bat
@@ -1,5 +1,5 @@
copy ..\FakeXrmEasy\bin\Debug\FakeXrmEasy.dll .\build\lib\net40
cd build
nuget pack FakeXrmEasy.dll.nuspec
-nuget push FakeXrmEasy.1.8.1.nupkg
+nuget push FakeXrmEasy.1.8.2.nupkg
pause
\ No newline at end of file
diff --git a/FakeXrmEasy/Extensions/EntityExtensions.cs b/FakeXrmEasy/Extensions/EntityExtensions.cs
index f125fdbc..4f82eaee 100644
--- a/FakeXrmEasy/Extensions/EntityExtensions.cs
+++ b/FakeXrmEasy/Extensions/EntityExtensions.cs
@@ -35,9 +35,14 @@ public static Entity AddAttribute(this Entity e, string key, object value)
///
public static Entity ProjectAttributes(this Entity e, ColumnSet columnSet, XrmFakedContext context)
{
- if (columnSet == null) return e;
+ return ProjectAttributes(e, new QueryExpression() { ColumnSet = columnSet }, context);
+ }
- if (columnSet.AllColumns)
+ public static Entity ProjectAttributes(this Entity e, QueryExpression qe, XrmFakedContext context)
+ {
+ if (qe.ColumnSet == null) return e;
+
+ if (qe.ColumnSet.AllColumns)
{
return e; //return all the original attributes
}
@@ -62,7 +67,7 @@ public static Entity ProjectAttributes(this Entity e, ColumnSet columnSet, XrmFa
else
projected = new Entity(e.LogicalName) { Id = e.Id };
- foreach (var attKey in columnSet.Columns)
+ foreach (var attKey in qe.ColumnSet.Columns)
{
if (e.Attributes.ContainsKey(attKey))
projected[attKey] = e[attKey];
@@ -76,12 +81,22 @@ public static Entity ProjectAttributes(this Entity e, ColumnSet columnSet, XrmFa
}
}
- //Plus the aliased attributes, if any
- foreach (var attKey in e.Attributes.Keys)
+ //Plus attributes from joins
+ foreach(var le in qe.LinkEntities)
{
- if(e[attKey] is AliasedValue && !projected.Attributes.ContainsKey(attKey))
- projected[attKey] = e[attKey];
+ foreach (var attKey in le.Columns.Columns)
+ {
+ var sAlias = string.IsNullOrWhiteSpace(le.EntityAlias) ? le.LinkToEntityName : le.EntityAlias;
+ var linkedAttKey = sAlias + "." + attKey;
+ if (e.Attributes.ContainsKey(linkedAttKey) || le.Columns.AllColumns)
+ projected[linkedAttKey] = e[linkedAttKey];
+ }
}
+ //foreach (var attKey in e.Attributes.Keys)
+ //{
+ // if(e[attKey] is AliasedValue && !projected.Attributes.ContainsKey(attKey))
+ // projected[attKey] = e[attKey];
+ //}
return projected;
}
}
diff --git a/FakeXrmEasy/Properties/AssemblyInfo.cs b/FakeXrmEasy/Properties/AssemblyInfo.cs
index afe97e70..6946b0cb 100644
--- a/FakeXrmEasy/Properties/AssemblyInfo.cs
+++ b/FakeXrmEasy/Properties/AssemblyInfo.cs
@@ -32,6 +32,6 @@
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("1.8.1.0")]
-[assembly: AssemblyFileVersion("1.8.1.0")]
-[assembly: AssemblyInformationalVersion("1.8.1")]
+[assembly: AssemblyVersion("1.8.2.0")]
+[assembly: AssemblyFileVersion("1.8.2.0")]
+[assembly: AssemblyInformationalVersion("1.8.2")]
diff --git a/FakeXrmEasy/XrmFakedContext.Queries.cs b/FakeXrmEasy/XrmFakedContext.Queries.cs
index b32e899e..cc57e323 100644
--- a/FakeXrmEasy/XrmFakedContext.Queries.cs
+++ b/FakeXrmEasy/XrmFakedContext.Queries.cs
@@ -117,6 +117,11 @@ public static IQueryable TranslateLinkedEntityToLinq(XrmFakedContext con
var inner = context.CreateQuery(le.LinkToEntityName);
+ if(!le.Columns.AllColumns && le.Columns.Columns.Count == 0)
+ {
+ le.Columns.AllColumns = true; //Add all columns in the joined entity, otherwise we can't filter by related attributes, then the Select will actually choose which ones we need
+ }
+
switch (le.JoinOperator)
{
case JoinOperator.Inner:
@@ -170,13 +175,12 @@ public static IQueryable TranslateQueryExpressionToLinq(XrmFakedContext
// Compose the expression tree that represents the parameter to the predicate.
ParameterExpression entity = Expression.Parameter(typeof(Entity));
- var expTreeBody = TranslateFilterExpressionToExpression(qe.Criteria, entity);
+ var expTreeBody = TranslateQueryExpressionFiltersToExpression(qe, entity);
Expression> lambda = Expression.Lambda>(expTreeBody, entity);
query = query.Where(lambda);
//Project the attributes in the root column set (must be applied after the where clause, not before!!)
- if (qe.ColumnSet != null && !qe.ColumnSet.AllColumns)
- query = query.Select(x => x.ProjectAttributes(qe.ColumnSet, context));
+ query = query.Select(x => x.ProjectAttributes(qe, context));
//Sort results
if (qe.Orders != null)
@@ -208,6 +212,30 @@ protected static Expression TranslateConditionExpression(ConditionExpression c,
"Attributes"
);
+
+ //If the attribute comes from a joined entity, then we need to access the attribute from the join
+ //But the entity name attribute only exists >= 2013
+#if FAKE_XRM_EASY_2013 || FAKE_XRM_EASY_2015
+ string attributeName = "";
+
+ if (!string.IsNullOrWhiteSpace(c.EntityName))
+ {
+ attributeName = c.EntityName + "." + c.AttributeName;
+ }
+ else
+ attributeName = c.AttributeName;
+
+ Expression containsAttributeExpression = Expression.Call(
+ attributesProperty,
+ typeof(AttributeCollection).GetMethod("ContainsKey", new Type[] { typeof(string) }),
+ Expression.Constant(attributeName)
+ );
+
+ Expression getAttributeValueExpr = Expression.Property(
+ attributesProperty, "Item",
+ Expression.Constant(attributeName, typeof(string))
+ );
+#else
Expression containsAttributeExpression = Expression.Call(
attributesProperty,
typeof(AttributeCollection).GetMethod("ContainsKey", new Type[] { typeof(string) }),
@@ -215,9 +243,11 @@ protected static Expression TranslateConditionExpression(ConditionExpression c,
);
Expression getAttributeValueExpr = Expression.Property(
- attributesProperty, "Item",
- Expression.Constant(c.AttributeName, typeof(string))
- );
+ attributesProperty, "Item",
+ Expression.Constant(c.AttributeName, typeof(string))
+ );
+#endif
+
Expression getNonBasicValueExpr = getAttributeValueExpr;
@@ -288,6 +318,23 @@ protected static Expression GetAppropiateTypedValue(object value)
}
protected static Expression GetAppropiateCastExpressionBasedOnValue(Expression input, object value)
+ {
+ var typedExpression = GetAppropiateCastExpressionBasedOnValueInherentType(input, value);
+
+ //Now, any value (entity reference, string, int, etc,... could be wrapped in an AliasedValue object
+ //So let's add this
+ var getValueFromAliasedValueExp = Expression.Call(Expression.Convert(input, typeof(AliasedValue)),
+ typeof(AliasedValue).GetMethod("get_Value"));
+
+ var exp = Expression.Condition(Expression.TypeIs(input, typeof(AliasedValue)),
+ GetAppropiateCastExpressionBasedOnValueInherentType(getValueFromAliasedValueExp, value),
+ typedExpression //Not an aliased value
+ );
+
+ return exp;
+ }
+
+ protected static Expression GetAppropiateCastExpressionBasedOnValueInherentType(Expression input, object value)
{
if (value is Guid)
return GetAppropiateCastExpressionBasedGuid(input); //Could be compared against an EntityReference
@@ -297,42 +344,39 @@ protected static Expression GetAppropiateCastExpressionBasedOnValue(Expression i
return GetAppropiateCastExpressionBasedOnDecimal(input); //Could be compared against a Money
if (value is bool)
return GetAppropiateCastExpressionBasedOnBoolean(input); //Could be a BooleanManagedProperty
-
- //Other basic types conversions
- //Special case => datetime is sent as a string
if (value is string)
{
- DateTime dtDateTimeConversion;
- if (DateTime.TryParse(value.ToString(), out dtDateTimeConversion))
- {
- return Expression.Convert(input, typeof(DateTime));
- }
+ return GetAppropiateCastExpressionBasedOnString(input, value);
}
- return Expression.Convert(input, value.GetType()); //Default type conversion
+ return GetAppropiateCastExpressionDefault(input, value); //any other type
+ }
+ protected static Expression GetAppropiateCastExpressionBasedOnString(Expression input, object value)
+ {
+ DateTime dtDateTimeConversion;
+ if (DateTime.TryParse(value.ToString(), out dtDateTimeConversion))
+ {
+ return Expression.Convert(input, typeof(DateTime));
+ }
+ return GetAppropiateCastExpressionDefault(input, value); //Non datetime string
}
+ protected static Expression GetAppropiateCastExpressionDefault(Expression input, object value)
+ {
+ return Expression.Convert(input, value.GetType()); //Default type conversion
+ }
protected static Expression GetAppropiateCastExpressionBasedGuid(Expression input)
{
+ var getIdFromEntityReferenceExpr = Expression.Call(Expression.TypeAs(input, typeof(EntityReference)),
+ typeof(EntityReference).GetMethod("get_Id"));
+
return Expression.Condition(
Expression.TypeIs(input, typeof(EntityReference)), //If input is an entity reference, compare the Guid against the Id property
Expression.Convert(
- Expression.Call(Expression.TypeAs(input, typeof(EntityReference)),
- typeof(EntityReference).GetMethod("get_Id")),
+ getIdFromEntityReferenceExpr,
typeof(Guid)),
- Expression.Condition(Expression.AndAlso(Expression.TypeIs(input, typeof(AliasedValue)), //If input is an AliasedValue which has an EntityReference, compare against the Id value as well
- Expression.TypeIs(Expression.Call(Expression.TypeAs(input, typeof(AliasedValue)),
- typeof(AliasedValue).GetMethod("get_Value")),
- typeof(EntityReference))),
- Expression.Call(Expression.TypeAs(Expression.Convert(
- Expression.Call(Expression.TypeAs(input, typeof(AliasedValue)),
- typeof(AliasedValue).GetMethod("get_Value")),
- typeof(Guid))
- , typeof(EntityReference)),
- typeof(EntityReference).GetMethod("get_Id")),
-
- Expression.Condition(Expression.TypeIs(input, typeof(Guid)), //If any other case, then just compare it as a Guid directly
+ Expression.Condition(Expression.TypeIs(input, typeof(Guid)), //If any other case, then just compare it as a Guid directly
Expression.Convert(input, typeof(Guid)),
- Expression.Constant(Guid.Empty))));
+ Expression.Constant(Guid.Empty, typeof(Guid))));
}
@@ -525,6 +569,61 @@ protected static BinaryExpression TranslateMultipleFilterExpressions(List();
+ foreach(var le in qe.LinkEntities)
+ {
+ var e = TranslateLinkedEntityFilterExpressionToExpression(le, entity);
+ linkedEntitiesQueryExpressions.Add(e);
+ }
+
+ if(linkedEntitiesQueryExpressions.Count > 0 && qe.Criteria != null)
+ {
+ //Return the and of the two
+ Expression andExpression = Expression.Constant(true);
+ foreach(var e in linkedEntitiesQueryExpressions)
+ {
+ andExpression = Expression.And(e, andExpression);
+
+ }
+ var feExpression = TranslateFilterExpressionToExpression(qe.Criteria, entity);
+ return Expression.And(andExpression, feExpression);
+ }
+ else if (linkedEntitiesQueryExpressions.Count > 0)
+ {
+ //Linked entity expressions only
+ Expression andExpression = Expression.Constant(true);
+ foreach (var e in linkedEntitiesQueryExpressions)
+ {
+ andExpression = Expression.And(e, andExpression);
+
+ }
+ return andExpression;
+ }
+ else
+ {
+ //Criteria only
+ return TranslateFilterExpressionToExpression(qe.Criteria, entity);
+ }
+ }
protected static Expression TranslateFilterExpressionToExpression(FilterExpression fe, ParameterExpression entity)
{
if (fe == null) return Expression.Constant(true);