public void When_doing_a_crm_linq_query_with_an_equals_operator_record_is_returned() { var fakedContext = new XrmFakedContext(); var guid1 = Guid.NewGuid(); var guid2 = Guid.NewGuid(); fakedContext.Initialize(new List<Entity>() { new Contact() { Id = guid1, FirstName = "Jordi" }, new Contact() { Id = guid2, FirstName = "Other" } }); var service = fakedContext.GetFakedOrganizationService(); using (XrmServiceContext ctx = new XrmServiceContext(service)) { var matches = (from c in ctx.CreateQuery<Contact>() where c.FirstName.Equals("Jordi") select c).ToList(); Assert.True(matches.Count == 1); Assert.True(matches[0].FirstName.Equals("Jordi")); matches = (from c in ctx.CreateQuery<Contact>() where c.FirstName == "Jordi" //Using now equality operator select c).ToList(); Assert.True(matches.Count == 1); Assert.True(matches[0].FirstName.Equals("Jordi")); } }
public void When_executing_a_query_expression_with_2_filters_combined_with_an_or_filter_right_result_is_returned() { var context = new XrmFakedContext(); var contact1 = new Entity("contact") { Id = Guid.NewGuid() }; contact1["fullname"] = "Contact 1"; contact1["firstname"] = "First 1"; var contact2 = new Entity("contact") { Id = Guid.NewGuid() }; contact2["fullname"] = "Contact 2"; contact2["firstname"] = "First 2"; context.Initialize(new List<Entity>() { contact1, contact2 }); var qe = new QueryExpression() { EntityName = "contact" }; qe.ColumnSet = new ColumnSet(true); var filter1 = new FilterExpression(); filter1.AddCondition(new ConditionExpression("fullname", ConditionOperator.Equal, "Contact 1")); var filter2 = new FilterExpression(); filter2.AddCondition(new ConditionExpression("fullname", ConditionOperator.Equal, "Contact 2")); qe.Criteria = new FilterExpression(LogicalOperator.Or); qe.Criteria.AddFilter(filter1); qe.Criteria.AddFilter(filter2); var result = XrmFakedContext.TranslateQueryExpressionToLinq(context, qe).ToList(); Assert.True(result.Count == 2); }
public void When_an_entity_is_created_with_an_empty_logical_name_an_exception_is_thrown() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var e = new Entity("") { Id = Guid.Empty }; var ex = Assert.Throws<InvalidOperationException>(() => service.Create(e)); Assert.Equal(ex.Message, "The LogicalName property must not be empty"); }
public static void When_using_proxy_types_assembly_the_attribute_metadata_is_inferred_from_the_proxy_types_assembly() { var fakedContext = new XrmFakedContext(); fakedContext.ProxyTypesAssembly = Assembly.GetExecutingAssembly(); var contact1 = new Entity("contact") { Id = Guid.NewGuid() }; contact1["fullname"] = "Contact 1"; contact1["firstname"] = "First 1"; var contact2 = new Entity("contact") { Id = Guid.NewGuid() }; contact2["fullname"] = "Contact 2"; contact2["firstname"] = "First 2"; fakedContext.Initialize(new List<Entity>() { contact1, contact2 }); var guid = Guid.NewGuid(); //Empty contecxt (no Initialize), but we should be able to query any typed entity without an entity not found exception var service = fakedContext.GetFakedOrganizationService(); using (XrmServiceContext ctx = new XrmServiceContext(service)) { var contact = (from c in ctx.CreateQuery<Contact>() where c.FirstName.Equals("First 1") select c).ToList(); Assert.True(contact.Count == 1); } }
public void When_the_create_task_activity_is_executed_a_task_is_created_in_the_context() { var fakedContext = new XrmFakedContext(); fakedContext.ProxyTypesAssembly = Assembly.GetExecutingAssembly(); var guid1 = Guid.NewGuid(); var account = new Account() { Id = guid1 }; fakedContext.Initialize(new List<Entity>() { account }); //Inputs var inputs = new Dictionary<string, object>() { { "inputEntity", account.ToEntityReference() } }; var result = fakedContext.ExecuteCodeActivity<CreateTaskActivity>(inputs); //The wf creates an activity, so make sure it is created var tasks = (from t in fakedContext.CreateQuery<Task>() select t).ToList(); //The activity creates a taks Assert.True(tasks.Count == 1); var output = result["taskCreated"] as EntityReference; //Task created contains the account passed as the regarding Id Assert.True(tasks[0].RegardingObjectId != null && tasks[0].RegardingObjectId.Id.Equals(guid1)); //Same task created is returned Assert.Equal(output.Id, tasks[0].Id); }
public void Should_Not_Change_Context_Objects_Without_Update() { var entityId = Guid.NewGuid(); var context = new XrmFakedContext(); var service = context.GetOrganizationService(); context.Initialize(new[] { new Entity ("account") { Id = entityId, Attributes = new AttributeCollection { { "accountname", "Adventure Works" } } } }); var firstRetrieve = service.Retrieve("account", entityId, new ColumnSet(true)); var secondRetrieve = service.Retrieve("account", entityId, new ColumnSet(true)); firstRetrieve["accountname"] = "Updated locally"; Assert.Equal("Updated locally", firstRetrieve["accountname"]); Assert.Equal("Adventure Works", secondRetrieve["accountname"]); }
public static void When_a_query_by_attribute_is_executed_when_one_attribute_right_result_is_returned() { var context = new XrmFakedContext(); var account = new Account() {Id = Guid.NewGuid(), Name = "Test"}; var account2 = new Account() { Id = Guid.NewGuid(), Name = "Other account!" }; context.Initialize(new List<Entity>() { account, account2 }); var service = context.GetFakedOrganizationService(); QueryByAttribute query = new QueryByAttribute(); query.Attributes.AddRange(new string[] { "name" }); query.ColumnSet = new ColumnSet(new string[] { "name" }); query.EntityName = Account.EntityLogicalName; query.Values.AddRange(new object[] { "Test" }); //Execute using a request to test the OOB (XRM) message contracts RetrieveMultipleRequest request = new RetrieveMultipleRequest(); request.Query = query; Collection<Entity> entityList = ((RetrieveMultipleResponse)service.Execute(request)).EntityCollection.Entities; Assert.True(entityList.Count == 1); Assert.Equal(entityList[0]["name"].ToString(), "Test"); }
public void Should_update_an_entity_when_calling_update() { var ctx = new XrmFakedContext(); var logSystem = A.Fake<IDetailedLog>(); var service = ctx.GetOrganizationService(); //Arrange var contact = new Entity("contact") { Id = Guid.NewGuid() }; contact["fullname"] = "Lionel Messi"; ctx.Initialize(new Entity[] { contact }); //Act var contactToUpdate = new Entity("contact") { Id = contact.Id }; contactToUpdate["fullname"] = "Luis Suárez"; var actions = new Actions(logSystem, service); actions.Update(contactToUpdate); //Assert var contacts = ctx.CreateQuery("contact").ToList(); Assert.Equal(1, contacts.Count); Assert.Equal(contacts[0]["fullname"], "Luis Suárez"); }
public void When_initialising_the_context_twice_exception_is_thrown() { var context = new XrmFakedContext(); var c = new Contact() { Id = Guid.NewGuid(), FirstName = "Lionel" }; Assert.DoesNotThrow(() => context.Initialize(new List<Entity>() { c })); Assert.Throws<Exception>(() => context.Initialize(new List<Entity>() { c })); }
public void When_doing_a_crm_linq_query_and_proxy_types_and_a_selected_attribute_returned_projected_entity_is_thesubclass() { var fakedContext = new XrmFakedContext(); var guid1 = Guid.NewGuid(); var guid2 = Guid.NewGuid(); fakedContext.Initialize(new List<Entity>() { new Contact() { Id = guid1, FirstName = "Jordi" }, new Contact() { Id = guid2, FirstName = "Other" } }); var service = fakedContext.GetFakedOrganizationService(); using (XrmServiceContext ctx = new XrmServiceContext(service)) { var matches = (from c in ctx.CreateQuery<Contact>() where c.FirstName.Equals("Jordi") select new { FirstName = c.FirstName, CrmRecord = c }).ToList(); Assert.True(matches.Count == 1); Assert.True(matches[0].FirstName.Equals("Jordi")); Assert.IsAssignableFrom(typeof(Contact), matches[0].CrmRecord); Assert.True(matches[0].CrmRecord.GetType() == typeof(Contact)); } }
public void When_doing_a_crm_linq_query_and_proxy_types_projection_must_be_applied_after_where_clause() { var fakedContext = new XrmFakedContext(); fakedContext.ProxyTypesAssembly = Assembly.GetExecutingAssembly(); var guid1 = Guid.NewGuid(); var guid2 = Guid.NewGuid(); fakedContext.Initialize(new List<Entity>() { new Contact() { Id = guid1, FirstName = "Jordi", LastName = "Montana" }, new Contact() { Id = guid2, FirstName = "Other" } }); var service = fakedContext.GetFakedOrganizationService(); using (XrmServiceContext ctx = new XrmServiceContext(service)) { var matches = (from c in ctx.CreateQuery<Contact>() where c.LastName == "Montana" //Should be able to filter by a non-selected attribute select new { FirstName = c.FirstName }).ToList(); Assert.True(matches.Count == 1); Assert.True(matches[0].FirstName.Equals("Jordi")); } }
public void When_retrieve_is_invoked_with_a_null_columnset_exception_is_thrown() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var ex = Assert.Throws<InvalidOperationException>(() => service.Retrieve("account", Guid.NewGuid(), null)); Assert.Equal(ex.Message, "The columnset parameter must not be null."); }
public void When_retrieve_is_invoked_with_an_empty_guid_an_exception_is_thrown() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var ex = Assert.Throws<InvalidOperationException>(() => service.Retrieve("account", Guid.Empty, new ColumnSet())); Assert.Equal(ex.Message, "The id must not be empty."); }
public void When_a_null_entity_is_created_an_exception_is_thrown() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var ex = Assert.Throws<InvalidOperationException>(() => service.Create(null)); Assert.Equal(ex.Message, "The entity must not be null"); }
public void When_getting_a_fake_service_reference_it_uses_a_singleton_pattern() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var service2 = context.GetFakedOrganizationService(); Assert.Equal(service, service2); }
/// <summary> /// A fake retrieve method that will query the FakedContext to retrieve the specified /// entity and Guid, or null, if the entity was not found /// </summary> /// <param name="context">The faked context</param> /// <param name="fakedService">The faked service where the Retrieve method will be faked</param> /// <returns></returns> protected static void FakeRetrieve(XrmFakedContext context, IOrganizationService fakedService) { A.CallTo(() => fakedService.Retrieve(A<string>._, A<Guid>._, A<ColumnSet>._)) .ReturnsLazily((string entityName, Guid id, ColumnSet columnSet) => { if (string.IsNullOrWhiteSpace(entityName)) { throw new InvalidOperationException("The entity logical name must not be null or empty."); } if (id == Guid.Empty) { throw new InvalidOperationException("The id must not be empty."); } if (columnSet == null) { throw new InvalidOperationException("The columnset parameter must not be null."); } // Don't fail with invalid operation exception, if no record of this entity exists, but entity is known if (!context.Data.ContainsKey(entityName)) { if (context.ProxyTypesAssembly == null) { throw new InvalidOperationException(string.Format("The entity logical name {0} is not valid.", entityName)); } if (!context.ProxyTypesAssembly.GetTypes().Any(type => context.FindReflectedType(entityName) != null)) { throw new InvalidOperationException(string.Format("The entity logical name {0} is not valid.", entityName)); } } //Entity logical name exists, so , check if the requested entity exists if (context.Data.ContainsKey(entityName) && context.Data[entityName] != null && context.Data[entityName].ContainsKey(id)) { //Entity found => return only the subset of columns specified or all of them if (columnSet.AllColumns) return context.Data[entityName][id]; else { //Return the subset of columns requested only var foundEntity = context.Data[entityName][id]; Entity projected = foundEntity.ProjectAttributes(columnSet,context); return projected; } } else { //Entity not found in the context => return null throw new FaultException<OrganizationServiceFault>(new OrganizationServiceFault(), string.Format("{0} With Id = {1} Does Not Exist", entityName, id.ToString("D"))); } }); }
/// <summary> /// Fakes the RetrieveAttributeRequest that checks if an attribute exists for a given entity /// For simpicity, it asumes all attributes exist /// </summary> /// <param name="context"></param> /// <param name="fakedService"></param> protected static OrganizationResponse FakeRetrieveAttributeRequest(XrmFakedContext context, IOrganizationService fakedService, RetrieveAttributeRequest req) { var response = new RetrieveAttributeResponse { }; return response; }
// Test class constructor public AccountTests() { // Create fake service fakeContext = new XrmFakedContext(); fakeService = fakeContext.GetOrganizationService(); // Create real service realContext = new MyContext("XRM"); realService = realContext.GetOrganizationService(); }
public void When_initializing_the_context_with_an_entity_with_an_empty_logical_name_an_exception_is_thrown() { var context = new XrmFakedContext(); IEnumerable<Entity> data = new List<Entity>() { new Entity() { Id = Guid.NewGuid()} }; var ex = Assert.Throws<InvalidOperationException>(() => context.Initialize(data)); Assert.Equal(ex.Message, "An entity must not have a null or empty LogicalName property."); }
public void When_an_entity_is_updated_with_an_empty_guid_an_exception_is_thrown() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var e = new Entity("account") { Id = Guid.Empty }; var ex = Assert.Throws<InvalidOperationException>(() => service.Update(e)); Assert.Equal(ex.Message, "The Id property must not be empty"); }
public void When_initializing_the_context_with_an_entity_with_an_empty_guid_an_exception_is_thrown() { var context = new XrmFakedContext(); IEnumerable<Entity> data = new List<Entity>() { new Entity("account") { Id = Guid.Empty } }; var ex = Assert.Throws<InvalidOperationException>(() => context.Initialize(data)); Assert.Equal(ex.Message, "An entity with an empty Id can't be added"); }
public void When_initializing_the_context_with_a_dynamic_entity_with_a_primary_key_is_added_to_the_context() { var context = new XrmFakedContext(); IEnumerable<Entity> data = new List<Entity>() { new Entity("account") { Id = Guid.NewGuid(), Attributes = new AttributeCollection { { "accountid", Guid.NewGuid() } } } }; Assert.DoesNotThrow(() => context.Initialize(data)); Assert.True(context.Data.Count == 1); Assert.True(context.Data["account"].Count == 1); }
public static void When_a_who_am_i_request_is_invoked_the_caller_id_is_returned() { var context = new XrmFakedContext(); context.CallerId = new EntityReference() { Id = Guid.NewGuid(), Name = "Super Faked User" }; var service = context.GetFakedOrganizationService(); WhoAmIRequest req = new WhoAmIRequest(); var response = service.Execute(req) as WhoAmIResponse; Assert.Equal(response.UserId, context.CallerId.Id); }
public void When_adding_an_entity_the_returned_guid_must_not_be_empty_and_the_context_should_have_it() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var e = new Entity("account") { Id = Guid.Empty }; var guid = service.Create(e); Assert.True(guid != Guid.Empty); Assert.True(context.Data.Count == 1); Assert.True(context.Data["account"].Count == 1); }
public void When_the_account_number_plugin_is_executed_for_an_account_that_already_has_a_number_exception_is_thrown() { var fakedContext = new XrmFakedContext(); var guid1 = Guid.NewGuid(); var target = new Entity("account") { Id = guid1 }; target["accountnumber"] = 69; //Execute our plugin against a target thatcontains the accountnumber attribute will throw exception Assert.Throws<InvalidPluginExecutionException>(() => fakedContext.ExecutePluginWithTarget<AccountNumberPlugin>(target)); }
public void Querying_a_dynamic_entity_not_present_in_the_context_should_return_no_records() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); //Find the contact var contact = (from c in context.CreateQuery("contact") select c).ToList(); Assert.Equal(contact.Count, 0); }
public void When_initializing_the_context_with_an_entity_it_should_have_default_createdon_createdby_modifiedon_and_modifiedby_attributes() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var e = new Entity("account") { Id = Guid.NewGuid() }; context.Initialize(new List<Entity>() { e }); Assert.True(e.Attributes.ContainsKey("createdon")); Assert.True(e.Attributes.ContainsKey("modifiedon")); Assert.True(e.Attributes.ContainsKey("createdby")); Assert.True(e.Attributes.ContainsKey("modifiedby")); }
public void When_retrieve_is_invoked_with_an_empty_logical_name_an_exception_is_thrown() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var ex = Assert.Throws<InvalidOperationException>(() => service.Retrieve(null,Guid.Empty,new ColumnSet())); Assert.Equal(ex.Message, "The entity logical name must not be null or empty."); ex = Assert.Throws<InvalidOperationException>(() => service.Retrieve("", Guid.Empty, new ColumnSet())); Assert.Equal(ex.Message, "The entity logical name must not be null or empty."); ex = Assert.Throws<InvalidOperationException>(() => service.Retrieve(" ", Guid.Empty, new ColumnSet())); Assert.Equal(ex.Message, "The entity logical name must not be null or empty."); }
public void When_initializing_the_context_with_an_entity_the_context_has_that_entity() { var context = new XrmFakedContext(); var guid = Guid.NewGuid(); IQueryable<Entity> data = new List<Entity>() { new Entity("account") { Id = guid } }.AsQueryable(); context.Initialize(data); Assert.True(context.Data.Count == 1); Assert.True(context.Data["account"].Count == 1); Assert.Equal(context.Data["account"][guid], data.FirstOrDefault()); }
public void When_the_add_activity_with_constant_is_executed_without_a_specific_instance_result_is_the_two_summands() { var fakedContext = new XrmFakedContext(); //Inputs var inputs = new Dictionary<string, object>() { { "firstSummand", 2 }, { "secondSummand", 3 } }; var result = fakedContext.ExecuteCodeActivity<AddActivityWithConstant>(inputs); Assert.True(((int)result["result"]).Equals(5)); }
internal static List <Entity> ProcessAggregateFetchXml(XrmFakedContext ctx, XDocument xmlDoc, List <Entity> resultOfQuery) { // Validate that <all-attributes> is not present, // that all attributes have groupby or aggregate, and an alias, // and that there is exactly 1 groupby. if (RetrieveFetchXmlNode(xmlDoc, "all-attributes") != null) { throw new Exception("Can't have <all-attributes /> present when using aggregate"); } var ns = xmlDoc.Root.Name.Namespace; var entityName = RetrieveFetchXmlNode(xmlDoc, "entity")?.GetAttribute("name")?.Value; if (string.IsNullOrEmpty(entityName)) { throw new Exception("Can't find entity name for aggregate query"); } var aggregates = new List <FetchAggregate>(); var groups = new List <FetchGrouping>(); foreach (var attr in xmlDoc.Descendants(ns + "attribute")) { //TODO: Find entity alias. Handle aliasedvalue in the query result. var alias = attr.GetAttribute("alias")?.Value; var logicalName = attr.GetAttribute("name")?.Value; if (string.IsNullOrEmpty("alias")) { throw new Exception("Missing alias for attribute in aggregate fetch xml"); } if (string.IsNullOrEmpty("name")) { throw new Exception("Missing name for attribute in aggregate fetch xml"); } if (attr.IsAttributeTrue("groupby")) { var dategrouping = attr.GetAttribute("dategrouping")?.Value; if (dategrouping != null) { DateGroupType t; if (!Enum.TryParse(dategrouping, true, out t)) { throw new Exception("Unknown dategrouping value '" + dategrouping + "'"); } groups.Add(new DateTimeGroup() { Type = t, OutputAlias = alias, Attribute = logicalName }); } else { groups.Add(new SimpleValueGroup() { OutputAlias = alias, Attribute = logicalName }); } } else { var agrFn = attr.GetAttribute("aggregate")?.Value; if (string.IsNullOrEmpty(agrFn)) { throw new Exception("Attributes must have be aggregated or grouped by when using aggregation"); } FetchAggregate newAgr = null; switch (agrFn?.ToLower()) { case "count": newAgr = new CountAggregate(); break; case "countcolumn": if (attr.IsAttributeTrue("distinct")) { newAgr = new CountDistinctAggregate(); } else { newAgr = new CountColumnAggregate(); } break; case "min": newAgr = new MinAggregate(); break; case "max": newAgr = new MaxAggregate(); break; case "avg": newAgr = new AvgAggregate(); break; case "sum": newAgr = new SumAggregate(); break; default: throw new Exception("Unknown aggregate function '" + agrFn + "'"); } newAgr.OutputAlias = alias; newAgr.Attribute = logicalName; aggregates.Add(newAgr); } } List <Entity> aggregateResult; if (groups.Any()) { aggregateResult = ProcessGroupedAggregate(entityName, resultOfQuery, aggregates, groups); } else { aggregateResult = new List <Entity>(); var ent = ProcessAggregatesForSingleGroup(entityName, resultOfQuery, aggregates); aggregateResult.Add(ent); } return(OrderAggregateResult(xmlDoc, aggregateResult.AsQueryable())); }
public static IQueryable <Entity> TranslateLinkedEntityToLinq(XrmFakedContext context, LinkEntity le, IQueryable <Entity> query, ColumnSet previousColumnSet, string linkFromAlias = "") { var leAlias = string.IsNullOrWhiteSpace(le.EntityAlias) ? le.LinkToEntityName : le.EntityAlias; context.EnsureEntityNameExistsInMetadata(le.LinkFromEntityName); context.EnsureEntityNameExistsInMetadata(le.LinkToEntityName); if (!context.AttributeExistsInMetadata(le.LinkToEntityName, le.LinkToAttributeName)) { OrganizationServiceFaultQueryBuilderNoAttributeException.Throw(le.LinkToAttributeName); } var inner = context.CreateQuery <Entity>(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 //} if (string.IsNullOrWhiteSpace(linkFromAlias)) { linkFromAlias = le.LinkFromAttributeName; } else { linkFromAlias += "." + le.LinkFromAttributeName; } switch (le.JoinOperator) { case JoinOperator.Inner: case JoinOperator.Natural: query = query.Join(inner, outerKey => outerKey.KeySelector(linkFromAlias, context), innerKey => innerKey.KeySelector(le.LinkToAttributeName, context), (outerEl, innerEl) => outerEl .JoinAttributes(innerEl, new ColumnSet(true), leAlias, context)); break; case JoinOperator.LeftOuter: query = query.GroupJoin(inner, outerKey => outerKey.KeySelector(le.LinkFromAttributeName, context), innerKey => innerKey.KeySelector(le.LinkToAttributeName, context), (outerEl, innerElemsCol) => new { outerEl, innerElemsCol }) .SelectMany(x => x.innerElemsCol.DefaultIfEmpty() , (x, y) => x.outerEl .JoinAttributes(y, new ColumnSet(true), leAlias, context)); break; default: //This shouldn't be reached as there are only 3 types of Join... throw new PullRequestException(string.Format("The join operator {0} is currently not supported. Feel free to implement and send a PR.", le.JoinOperator)); } //Process nested linked entities recursively foreach (LinkEntity nestedLinkedEntity in le.LinkEntities) { if (string.IsNullOrWhiteSpace(le.EntityAlias)) { le.EntityAlias = le.LinkToEntityName; } query = TranslateLinkedEntityToLinq(context, nestedLinkedEntity, query, le.Columns, le.EntityAlias); } return(query); }
public static QueryExpression TranslateFetchXmlToQueryExpression(XrmFakedContext context, string fetchXml) { return(TranslateFetchXmlDocumentToQueryExpression(context, ParseFetchXml(fetchXml))); }
public static IQueryable <Entity> TranslateQueryExpressionToLinq(XrmFakedContext context, QueryExpression qe) { if (qe == null) { return(null); } //Start form the root entity and build a LINQ query to execute the query against the In-Memory context: context.EnsureEntityNameExistsInMetadata(qe.EntityName); IQueryable <Entity> query = null; query = context.CreateQuery <Entity>(qe.EntityName); //Add as many Joins as linked entities foreach (LinkEntity le in qe.LinkEntities) { query = TranslateLinkedEntityToLinq(context, le, query, qe.ColumnSet); } // Compose the expression tree that represents the parameter to the predicate. ParameterExpression entity = Expression.Parameter(typeof(Entity)); var expTreeBody = TranslateQueryExpressionFiltersToExpression(context, qe, entity); Expression <Func <Entity, bool> > lambda = Expression.Lambda <Func <Entity, bool> >(expTreeBody, entity); query = query.Where(lambda); //Project the attributes in the root column set (must be applied after the where clause, not before!!) query = query.Select(x => x.Clone(x.GetType()).ProjectAttributes(qe, context)); //Sort results if (qe.Orders != null) { if (qe.Orders.Count > 0) { IOrderedQueryable <Entity> orderedQuery = null; var order = qe.Orders[0]; if (order.OrderType == OrderType.Ascending) { orderedQuery = query.OrderBy(e => e.Attributes.ContainsKey(order.AttributeName) ? e[order.AttributeName] : null, new XrmOrderByAttributeComparer()); } else { orderedQuery = query.OrderByDescending(e => e.Attributes.ContainsKey(order.AttributeName) ? e[order.AttributeName] : null, new XrmOrderByAttributeComparer()); } //Subsequent orders should use ThenBy and ThenByDescending for (var i = 1; i < qe.Orders.Count; i++) { var thenOrder = qe.Orders[i]; if (thenOrder.OrderType == OrderType.Ascending) { orderedQuery = orderedQuery.ThenBy(e => e.Attributes.ContainsKey(thenOrder.AttributeName) ? e[thenOrder.AttributeName] : null, new XrmOrderByAttributeComparer()); } else { orderedQuery = orderedQuery.ThenByDescending(e => e[thenOrder.AttributeName], new XrmOrderByAttributeComparer()); } } query = orderedQuery; } } //Apply TopCount if (qe.TopCount != null) { query = query.Take(qe.TopCount.Value); } return(query); }
protected static Expression TranslateConditionExpression(XrmFakedContext context, ConditionExpression c, ParameterExpression entity) { Expression attributesProperty = Expression.Property( entity, "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 || FAKE_XRM_EASY_2016 || FAKE_XRM_EASY_365 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) }), Expression.Constant(c.AttributeName) ); Expression getAttributeValueExpr = Expression.Property( attributesProperty, "Item", Expression.Constant(c.AttributeName, typeof(string)) ); #endif Expression getNonBasicValueExpr = getAttributeValueExpr; switch (c.Operator) { case ConditionOperator.Equal: case ConditionOperator.Today: case ConditionOperator.Yesterday: case ConditionOperator.Tomorrow: case ConditionOperator.EqualUserId: return(TranslateConditionExpressionEqual(context, c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.NotEqualUserId: return(Expression.Not(TranslateConditionExpressionEqual(context, c, getNonBasicValueExpr, containsAttributeExpression))); case ConditionOperator.BeginsWith: case ConditionOperator.Like: return(TranslateConditionExpressionLike(c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.EndsWith: return(TranslateConditionExpressionEndsWith(c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.Contains: return(TranslateConditionExpressionContains(c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.NotEqual: return(Expression.Not(TranslateConditionExpressionEqual(context, c, getNonBasicValueExpr, containsAttributeExpression))); case ConditionOperator.DoesNotBeginWith: case ConditionOperator.DoesNotEndWith: case ConditionOperator.NotLike: case ConditionOperator.DoesNotContain: return(Expression.Not(TranslateConditionExpressionLike(c, getNonBasicValueExpr, containsAttributeExpression))); case ConditionOperator.Null: return(TranslateConditionExpressionNull(c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.NotNull: return(Expression.Not(TranslateConditionExpressionNull(c, getNonBasicValueExpr, containsAttributeExpression))); case ConditionOperator.GreaterThan: return(TranslateConditionExpressionGreaterThan(c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.GreaterEqual: return(TranslateConditionExpressionGreaterThanOrEqual(context, c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.LessThan: return(TranslateConditionExpressionLessThan(c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.LessEqual: return(TranslateConditionExpressionLessThanOrEqual(context, c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.In: return(TranslateConditionExpressionIn(c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.NotIn: return(Expression.Not(TranslateConditionExpressionIn(c, getNonBasicValueExpr, containsAttributeExpression))); case ConditionOperator.On: return(TranslateConditionExpressionEqual(context, c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.NotOn: return(Expression.Not(TranslateConditionExpressionEqual(context, c, getNonBasicValueExpr, containsAttributeExpression))); case ConditionOperator.OnOrAfter: return(Expression.Or( TranslateConditionExpressionEqual(context, c, getNonBasicValueExpr, containsAttributeExpression), TranslateConditionExpressionGreaterThan(c, getNonBasicValueExpr, containsAttributeExpression))); case ConditionOperator.OnOrBefore: return(Expression.Or( TranslateConditionExpressionEqual(context, c, getNonBasicValueExpr, containsAttributeExpression), TranslateConditionExpressionLessThan(c, getNonBasicValueExpr, containsAttributeExpression))); case ConditionOperator.Between: if (c.Values.Count != 2) { throw new Exception("Between operator requires exactly 2 values."); } return(TranslateConditionExpressionBetween(c, getNonBasicValueExpr, containsAttributeExpression)); case ConditionOperator.NotBetween: if (c.Values.Count != 2) { throw new Exception("Not-Between operator requires exactly 2 values."); } return(Expression.Not(TranslateConditionExpressionBetween(c, getNonBasicValueExpr, containsAttributeExpression))); default: throw new PullRequestException(string.Format("Operator {0} not yet implemented for condition expression", c.Operator.ToString())); } }
protected static Expression TranslateConditionExpressionLessThanOrEqual(XrmFakedContext context, ConditionExpression c, Expression getAttributeValueExpr, Expression containsAttributeExpr) { return(Expression.Or( TranslateConditionExpressionEqual(context, c, getAttributeValueExpr, containsAttributeExpr), TranslateConditionExpressionLessThan(c, getAttributeValueExpr, containsAttributeExpr))); }
protected static Expression TranslateLinkedEntityFilterExpressionToExpression(XrmFakedContext context, LinkEntity le, ParameterExpression entity) { //In CRM 2011, condition expressions are at the LinkEntity level without an entity name //From CRM 2013, condition expressions were moved to outside the LinkEntity object at the QueryExpression level, //with an EntityName alias attribute //If we reach this point, it means we are translating filters at the Link Entity level (2011), //Therefore we need to prepend the alias attribute because the code to generate attributes for Joins (JoinAttribute extension) is common across versions if (le.LinkCriteria != null) { foreach (var ce in le.LinkCriteria.Conditions) { var entityAlias = !string.IsNullOrEmpty(le.EntityAlias) ? le.EntityAlias : le.LinkToEntityName; ce.AttributeName = entityAlias + "." + ce.AttributeName; } } return(TranslateFilterExpressionToExpression(context, le.LinkCriteria, entity)); }
/// <summary> /// A fake retrieve method that will query the FakedContext to retrieve the specified /// entity and Guid, or null, if the entity was not found /// </summary> /// <param name="context">The faked context</param> /// <param name="fakedService">The faked service where the Retrieve method will be faked</param> /// <returns></returns> protected static void FakeRetrieve(XrmFakedContext context, IOrganizationService fakedService) { A.CallTo(() => fakedService.Retrieve(A <string> ._, A <Guid> ._, A <ColumnSet> ._)) .ReturnsLazily((string entityName, Guid id, ColumnSet columnSet) => { if (string.IsNullOrWhiteSpace(entityName)) { throw new InvalidOperationException("The entity logical name must not be null or empty."); } if (id == Guid.Empty) { throw new InvalidOperationException("The id must not be empty."); } if (columnSet == null) { throw new InvalidOperationException("The columnset parameter must not be null."); } // Don't fail with invalid operation exception, if no record of this entity exists, but entity is known if (!context.Data.ContainsKey(entityName)) { if (context.ProxyTypesAssembly == null) { throw new InvalidOperationException($"The entity logical name {entityName} is not valid."); } if (!context.ProxyTypesAssembly.GetTypes().Any(type => context.FindReflectedType(entityName) != null)) { throw new InvalidOperationException($"The entity logical name {entityName} is not valid."); } } //Return the subset of columns requested only var reflectedType = context.FindReflectedType(entityName); //Entity logical name exists, so , check if the requested entity exists if (context.Data.ContainsKey(entityName) && context.Data[entityName] != null && context.Data[entityName].ContainsKey(id)) { //Entity found => return only the subset of columns specified or all of them var foundEntity = context.Data[entityName][id].Clone(reflectedType); if (columnSet.AllColumns) { foundEntity.ApplyDateBehaviour(context); return(foundEntity); } else { var projected = foundEntity.ProjectAttributes(columnSet, context); projected.ApplyDateBehaviour(context); return(projected); } } else { // Entity not found in the context => FaultException throw new FaultException <OrganizationServiceFault>(new OrganizationServiceFault(), $"{entityName} With Id = {id:D} Does Not Exist"); } }); }