Esempio n. 1
0
        public void Can_Register_Crm_Plugin()
        {
            var serviceProvider = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig(), new CrmClientCredentialsProvider());
            //PluginAssembly, PluginType, SdkMessageProcessingStep, and SdkMessageProcessingStepImage.

            var crmOrgConnectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];

            var deployer = DeploymentBuilder.CreateDeployment()
                           .ForTheAssemblyContainingThisPlugin <CrmSyncChangeTrackerPlugin>("Test plugin assembly")
                           .RunsInSandboxMode()
                           .RegisterInDatabase()
                           .HasPlugin <CrmSyncChangeTrackerPlugin>()
                           .WhichExecutesOn(SdkMessageNames.Create, "contact")
                           .Synchronously()
                           .PostOperation()
                           .OnlyOnCrmServer()
                           .DeployTo(crmOrgConnectionString.ConnectionString);

            RegistrationInfo = deployer.Deploy();
            if (!RegistrationInfo.Success)
            {
                Assert.Fail("Registration failed..");
                //deployer.Undeploy(updateInfo);
                //Console.WriteLine("Registration was rolled back..");
            }
        }
        public void Load_ShouldInitializeCrmServiceProviderWithSpecifiqueInstance()
        {
            var serviceProvider = new CrmServiceProvider();

            CrmServiceProvider.Load(serviceProvider);

            Assert.That(CrmServiceProvider.Current, Is.SameAs(serviceProvider));
        }
Esempio n. 3
0
        /// <summary>
        /// Deletes any entities related to the registration, removing the registration from CRM.
        /// </summary>
        /// <param name="regisrationInfo"></param>
        public void Undeploy(RegistrationInfo regisrationInfo)
        {
            // Ensure custom test entity removed.
            var service = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig(), new CrmClientCredentialsProvider());

            // clean up in reverse creation order.

            regisrationInfo.RelatedEntities.Reverse();
            DeleteEntities(service, regisrationInfo.RelatedEntities);
        }
Esempio n. 4
0
        public void Experiment_For_Saving_Entity_Metadata_To_File(string entityName)
        {
            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var orgService = serviceProvider.GetOrganisationService();

            using (orgService as IDisposable)
            {
                MetadataFilterExpression entityFilter = new MetadataFilterExpression(LogicalOperator.And);
                entityFilter.Conditions.Add(new MetadataConditionExpression("LogicalName", MetadataConditionOperator.Equals, entityName));



                EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
                {
                    Criteria   = entityFilter,
                    Properties = new MetadataPropertiesExpression()
                    {
                        AllProperties = true
                    }
                };
                RetrieveMetadataChangesRequest retrieveMetadataChangesRequest = new RetrieveMetadataChangesRequest()
                {
                    Query = entityQueryExpression,
                    ClientVersionStamp = null
                };
                RetrieveMetadataChangesResponse response = (RetrieveMetadataChangesResponse)orgService.Execute(retrieveMetadataChangesRequest);
                var entityMetadata = response.EntityMetadata[0];



                var path          = Environment.CurrentDirectory;
                var shortFileName = entityName + "Metadata.xml";


                var fileName   = System.IO.Path.Combine(path, shortFileName);
                var serialised = EntityMetadataUtils.SerializeMetaData(entityMetadata, System.Xml.Formatting.Indented);
                using (var writer = new System.IO.StreamWriter(fileName))
                {
                    writer.Write(serialised);
                    writer.Flush();
                    writer.Close();
                }

                if (!File.Exists(fileName))
                {
                    throw new FileNotFoundException("Could not save metadata file for entity " + entityName);
                }
            }
        }
Esempio n. 5
0
        internal override bool Check(Dynamics.ICrmServiceProvider crmServiceProvider, out string failureMessage)
        {
            // create connection
            var crmServiceProvder = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = ConnectionString
            }, new CrmClientCredentialsProvider());

            // Check sub requirements.
            return(base.Check(crmServiceProvder, out failureMessage));
        }
Esempio n. 6
0
        public void Experiment_For_Filters_2_With_Linq_Conversion()
        {
            // var sql = string.Format("Select C.firstname, C.lastname From contact Where firstname Like '%ax%' ");


            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var orgService = serviceProvider.GetOrganisationService() as CrmOrganizationServiceContext;

            using (orgService as IDisposable)
            {
                var contactsQuery = from c in orgService.CreateQuery("contact")
                                    join a in orgService.CreateQuery("customeraddress") on(Guid) c["contactid"] equals
                                        (Guid) a["parentid"]
                                    where (((string)c["firstname"] == "Max" && (string)c["lastname"] == "Planck") ||
                                           ((string)c["firstname"] == "Albert" && (string)c["lastname"] == "Einstein")) ||
                                    (string)a["line1"] == "Line2"

                                    select c;


                IQueryProvider queryProvider = contactsQuery.Provider;

                MethodInfo      translateMethodInfo = queryProvider.GetType().GetMethod("Translate");
                QueryExpression query = (QueryExpression)translateMethodInfo.Invoke(queryProvider, new object[] { contactsQuery.Expression });

                QueryExpressionToFetchXmlRequest reqConvertToFetchXml = new QueryExpressionToFetchXmlRequest {
                    Query = query
                };
                QueryExpressionToFetchXmlResponse respConvertToFetchXml = (QueryExpressionToFetchXmlResponse)orgService.Execute(reqConvertToFetchXml);

                System.Diagnostics.Debug.Print(respConvertToFetchXml.FetchXml);


                var results     = contactsQuery.ToList();
                int resultCount = 0;
                foreach (var r in results)
                {
                    resultCount++;
                    // Console.WriteLine(string.Format("{0} {1} {2}", (string)r["firstname"], (string)r["lastname"], (string)r["line1"]));
                    Console.WriteLine(string.Format("{0} {1}", (string)r["firstname"], (string)r["lastname"]));
                }
                Console.WriteLine("There were " + resultCount + " results..");
            }
        }
Esempio n. 7
0
        public void Experiment_For_Min_Active_Row_Version()
        {
            // var sql = string.Format("Select C.firstname, C.lastname From contact Where firstname Like '%ax%' ");

            var           threadCount = 50;
            List <Thread> threads     = new List <Thread>();

            for (int i = 0; i < threadCount; i++)
            {
                var thread = new Thread((a) => DoSomeWork(a));
            }

            // now keep querying for min active row version..
            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var orgService = serviceProvider.GetOrganisationService();

            using (orgService as IDisposable)
            {
                // start some accounts being inserted on background thread..
                foreach (Thread thread in threads)
                {
                    thread.Start();
                }

                // Whilst that is happening keep querying min active row version..
                for (int i = 0; i < 100; i++)
                {
                    var accounts = orgService.RetrieveMultiple(new QueryExpression("account")
                    {
                        ColumnSet = new ColumnSet("accountid")
                    });
                    Console.WriteLine("min active is: " + accounts.MinActiveRowVersion);
                }
            }
            // ensure threads all finished.
            foreach (Thread thread in threads)
            {
                thread.Join();
            }
        }
Esempio n. 8
0
        public void Experiment_For_Filter_Groups()
        {
            // var sql = string.Format("Select C.firstname, C.lastname From contact Where firstname Like '%ax%' ");


            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var orgService = serviceProvider.GetOrganisationService();

            using (orgService as IDisposable)
            {
                // var request = new RetrieveMultipleRequest();
                var query = new QueryExpression("contact");
                // request.Query = query;
                query.ColumnSet.AddColumn("firstname");
                query.ColumnSet.AddColumn("lastname");
                var condition1 = new ConditionExpression("firstname", ConditionOperator.Equal, "Max");
                var condition2 = new ConditionExpression("lastname", ConditionOperator.Equal, "Planck");
                var filter1    = new FilterExpression(LogicalOperator.And);
                filter1.AddCondition(condition1);
                filter1.AddCondition(condition2);

                var condition3 = new ConditionExpression("firstname", ConditionOperator.Equal, "Albert");
                var filter2    = new FilterExpression(LogicalOperator.Or);
                filter2.AddCondition(condition3);
                filter2.AddFilter(filter1);

                query.Criteria.Filters.Clear();
                query.Criteria.AddFilter(filter2);

                var results     = orgService.RetrieveMultiple(query);
                int resultCount = 0;
                foreach (var r in results.Entities)
                {
                    resultCount++;
                    Console.WriteLine(string.Format("{0} {1}", (string)r["firstname"], (string)r["lastname"]));
                }
                Console.WriteLine("There were " + resultCount + " results..");
            }
        }
Esempio n. 9
0
        private async Task PassContextToPlugins(RemoteExecutionContext executionContext)
        {
            foreach (var plugin in Plugins)
            {
                var serviceProvider = new CrmServiceProvider(CrmPluginBrokerRole.Crm, executionContext);

                try
                {
                    await Task.Run(() => plugin.Execute(serviceProvider));
                }
                catch (Exception)
                {
                    Trace.TraceError(String.Format("Failed processing plugin: {0}", plugin.GetType()));

                    throw;
                }
            }
        }
Esempio n. 10
0
 public override void Open()
 {
     if (_State == ConnectionState.Closed)
     {
         ExecuteWithinStateTransition(
             ConnectionState.Connecting,
             f =>
         {
             _OrganizationService = CrmServiceProvider.GetOrganisationService();
             _ConnectionInfo      = _ConnectionCache.GetConnectionInfo(this);
         },
             ConnectionState.Open);
     }
     else
     {
         throw new InvalidOperationException("Connection can only be opened if it is currently in the closed state.");
     }
 }
Esempio n. 11
0
        private void DoSomeWork(object o)
        {
            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var orgService = serviceProvider.GetOrganisationService();

            using (orgService as IDisposable)
            {
                var account = new Entity("account");
                account["name"] = "test";
                orgService.Create(account);
            }
        }
Esempio n. 12
0
        public void Experiment_For_Filters_3()
        {
            // var sql = string.Format("Select C.firstname, C.lastname From contact Where firstname Like '%ax%' ");


            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var orgService = serviceProvider.GetOrganisationService();

            using (orgService as IDisposable)
            {
                var query = new QueryExpression("contact");
                query.Distinct = true;
                query.ColumnSet.AddColumns("firstname", "lastname");
                query.Criteria.FilterOperator = LogicalOperator.Or;
                var f = query.Criteria.AddFilter(LogicalOperator.And);
                f.AddCondition("firstname", ConditionOperator.Equal, "Max");
                f.AddCondition("lastname", ConditionOperator.Equal, "Planck");
                f = query.Criteria.AddFilter(LogicalOperator.And);
                f.AddCondition("firstname", ConditionOperator.Equal, "Albert");
                f.AddCondition("lastname", ConditionOperator.Equal, "Einstein");
                var a = query.AddLink("customeraddress", "contactid", "parentid");
                a.LinkCriteria.AddCondition("line1", ConditionOperator.Equal, "The secret moonbase");

                // var response = orgService.RetrieveMultiple(query);



                var results     = orgService.RetrieveMultiple(query);
                int resultCount = 0;
                foreach (var r in results.Entities)
                {
                    resultCount++;
                    Console.WriteLine(string.Format("{0} {1}", (string)r["firstname"], (string)r["lastname"]));
                }
                Console.WriteLine("There were " + resultCount + " results..");
            }
        }
Esempio n. 13
0
        public void Experiment_For_Crm_Version_Request()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var orgService = serviceProvider.GetOrganisationService();

            using (orgService as IDisposable)
            {
                var req  = new RetrieveVersionRequest();
                var resp = (RetrieveVersionResponse)orgService.Execute(req);
                //assigns the version to a string
                string versionNumber = resp.Version;
                Console.WriteLine(versionNumber);
            }
        }
Esempio n. 14
0
        public void Crm_Plugin_Captures_Creation_Version_On_Create_Of_Entity()
        {
            // create a new entity.

            var service = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig(), new CrmClientCredentialsProvider());

            using (var orgServiceContext = (OrganizationServiceContext)service.GetOrganisationService())
            {
                // Create a new entity record which should fire plugin in crm.
                var testEntity    = new Entity(this.TestEntityLogicalName);
                var nameAttribute = this.TestEntityMetadata.PrimaryNameAttribute;
                testEntity[nameAttribute] = "you shall pass!";
                var orgService  = (IOrganizationService)orgServiceContext;
                var newRecordId = orgService.Create(testEntity);

                Console.WriteLine("Record created: " + newRecordId);

                // pull back the record and verify the plugin captured the creation version of the record.
                var ent = orgService.Retrieve(this.TestEntityLogicalName, newRecordId, new ColumnSet(SyncColumnInfo.RowVersionAttributeName, SyncColumnInfo.CreatedRowVersionAttributeName));

                Assert.That(ent.Attributes.ContainsKey(SyncColumnInfo.CreatedRowVersionAttributeName));
                Assert.That(ent.Attributes.ContainsKey(SyncColumnInfo.RowVersionAttributeName));

                var rowVersion = (long)ent.Attributes[SyncColumnInfo.RowVersionAttributeName];
                Assert.That(rowVersion, Is.GreaterThan(0));

                var capturedCreationVersion = System.Convert.ToInt64((decimal)ent.Attributes[SyncColumnInfo.CreatedRowVersionAttributeName]);

                Assert.That(capturedCreationVersion, Is.GreaterThan(0));
                // the row version is incremented on every modification of the record - as the plugin modified it when saving the creation version this causes the
                // row version to be atleast 1 greater than creation version.
                // If many tests are executing in dynamics at the same time then the rowversion could be incrememnted by more than 1 as its globally unique.
                // so we make an allowance here of max 5 difference.
                Assert.That(rowVersion - capturedCreationVersion, Is.LessThan(5));
                Assert.That(rowVersion - capturedCreationVersion, Is.GreaterThan(-1));

                Console.WriteLine("Creation version is: " + capturedCreationVersion);
                Console.WriteLine("Row version is: " + rowVersion);
            }
        }
Esempio n. 15
0
        public void Experiment_For_Selecting_Entity_Metadata()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var orgService = serviceProvider.GetOrganisationService();

            using (orgService as IDisposable)
            {
                MetadataFilterExpression entityFilter = new MetadataFilterExpression(LogicalOperator.And);
                //  entityFilter.Conditions.Add(new MetadataConditionExpression("OneToManyRelationships", MetadataConditionOperator.NotEquals, null));


                var relationShipQuery = new RelationshipQueryExpression();
                MetadataFilterExpression relationShipFilter = new MetadataFilterExpression(LogicalOperator.And);
                relationShipFilter.Conditions.Add(new MetadataConditionExpression("RelationshipType", MetadataConditionOperator.Equals, RelationshipType.OneToManyRelationship));
                relationShipQuery.Criteria = relationShipFilter;

                var props = new MetadataPropertiesExpression();
                props.AllProperties = false;
                props.PropertyNames.Add("OneToManyRelationships");

                EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
                {
                    Criteria          = entityFilter,
                    Properties        = props,
                    RelationshipQuery = relationShipQuery
                };
                RetrieveMetadataChangesRequest retrieveMetadataChangesRequest = new RetrieveMetadataChangesRequest()
                {
                    Query = entityQueryExpression,
                    ClientVersionStamp = null
                };
                RetrieveMetadataChangesResponse response = (RetrieveMetadataChangesResponse)orgService.Execute(retrieveMetadataChangesRequest);
            }
        }
Esempio n. 16
0
        public void Should_Get_Metadata()
        {
            // arrange
            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var sut = new EntityMetadataRepository(serviceProvider);
            // act
            var contactMetadata = sut.GetEntityMetadata("contact");

            // assert
            Assert.That(contactMetadata, Is.Not.Null);
            Assert.That(contactMetadata, Is.Not.Null);

            Assert.That(contactMetadata.Attributes, Is.Not.Null);
            Assert.That(contactMetadata.Attributes.FirstOrDefault(a => a.LogicalName == "firstname"), Is.Not.Null);
            Assert.That(contactMetadata.Attributes.FirstOrDefault(a => a.LogicalName == "lastname"), Is.Not.Null);
        }
Esempio n. 17
0
        public void Can_Sync_Single_Insert_On_Client_Roundtrip_With_Server()
        {
            var sampleStats     = new SampleStats();
            var crmConnString   = GetCrmServiceProvider().ConnectionProvider.OrganisationServiceConnectionString;
            var sampleSyncAgent = new TestDynamicsCrmSyncAgent(SqlCompactDatabaseConnectionString, crmConnString);

            SyncStatistics syncStatistics = sampleSyncAgent.Synchronize();

            sampleStats.DisplayStats(syncStatistics, "initial");

            // get number of existing records.
            // assert that the client only has one record and that the server only has 1 record.
            int existingCount = 0;

            using (var clientConn = new SqlCeConnection(SqlCompactDatabaseConnectionString))
            {
                clientConn.Open();
                using (var sqlCeCommand = clientConn.CreateCommand())
                {
                    sqlCeCommand.CommandText = string.Format("SELECT COUNT({0}) FROM {1}", TestDynamicsCrmServerSyncProvider.IdAttributeName, TestDynamicsCrmServerSyncProvider.TestEntityName);
                    existingCount            = (int)sqlCeCommand.ExecuteScalar();
                    // Assert.That(rowCount, Is.EqualTo(1), string.Format("Only 1 record was synchronised however {0} records ended up in the client database!", rowCount));
                }
                clientConn.Close();
            }


            //Make changes on the client.
            // We will insert into the same columns on the client that the server sync provider includes in its server insert statement,
            // with exception of the sync client id field (thats only provided during a sync)

            var columnsForClientInsert = TestDynamicsCrmServerSyncProvider.InsertColumns.ToList();
            var syncClientIdColumn     = columnsForClientInsert.First(c => c.AttributeName == SyncColumnInfo.CreatedBySyncClientIdAttributeName);

            columnsForClientInsert.Remove(syncClientIdColumn);
            sampleSyncAgent.ClientSyncProvider.InsertTestRecord(1, columnsForClientInsert);

            //Now sync the new record on the client to the server.
            syncStatistics = sampleSyncAgent.Synchronize();
            sampleStats.DisplayStats(syncStatistics, "second");

            // Verfiy new record is added on server.
            Assert.That(syncStatistics.DownloadChangesFailed, Is.EqualTo(0), "There were failed downloads during the sync.");
            Assert.That(syncStatistics.UploadChangesFailed, Is.EqualTo(0), "There were failed uploads during the sync.");
            var service = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig(), new CrmClientCredentialsProvider());

            using (var orgService = service.GetOrganisationService() as OrganizationServiceContext)
            {
                var entity = (from a in orgService.CreateQuery(TestDynamicsCrmServerSyncProvider.TestEntityName) orderby a["createdon"] descending select a).FirstOrDefault();
                Assert.That(entity, Is.Not.Null);
                var clientId = entity.Attributes[SyncColumnInfo.CreatedBySyncClientIdAttributeName];
                Assert.That(clientId, Is.EqualTo(SelectIncrementalCreatesCommand.SyncClientId), "A record was inserted during synchronisation, however it did not have a client id set.");

                // verify all the other fields are set.
                foreach (var col in columnsForClientInsert)
                {
                    var testAttribute = entity.Attributes[col.AttributeName];
                    Assert.That(testAttribute, Is.Not.Null, "A record was inserted during synchronisation, however it did not have a value for the attribute:  " + col.AttributeName);
                    Assert.That(testAttribute.ToString(), Is.Not.EqualTo(""), "The attribute " + col.AttributeName + " had a value inserted to the client but was then synced to the server, and was blank on the server after the sync finished.");
                }
            }

            // Now sync one more time and verify that the new reocrd that has been applied to the server does not come back as an insert on the client again!
            // The server updates the record as its saved to the server so it should come back as an update with the server generated values set on the record.
            syncStatistics = sampleSyncAgent.Synchronize();
            sampleStats.DisplayStats(syncStatistics, "third");

            // assert that the client only has one record and that the server only has 1 record.
            using (var clientConn = new SqlCeConnection(SqlCompactDatabaseConnectionString))
            {
                clientConn.Open();
                using (var sqlCeCommand = clientConn.CreateCommand())
                {
                    sqlCeCommand.CommandText = string.Format("SELECT COUNT({0}) FROM {1}", TestDynamicsCrmServerSyncProvider.IdAttributeName, TestDynamicsCrmServerSyncProvider.TestEntityName);
                    var rowCount = (int)sqlCeCommand.ExecuteScalar();
                    Assert.That(rowCount, Is.EqualTo(existingCount + 1), string.Format("Only 1 new record was created, however after a few synchronisations, {0} new records ended up in the client database!", rowCount - existingCount));
                }
                clientConn.Close();
            }
        }
Esempio n. 18
0
        public void Experiment_For_Filters_1()
        {
            // var sql = string.Format("Select C.firstname, C.lastname From contact Where firstname Like '%ax%' ");


            var connectionString = ConfigurationManager.ConnectionStrings["CrmOrganisation"];
            var serviceProvider  = new CrmServiceProvider(new ExplicitConnectionStringProviderWithFallbackToConfig()
            {
                OrganisationServiceConnectionString = connectionString.ConnectionString
            },
                                                          new CrmClientCredentialsProvider());

            var orgService = serviceProvider.GetOrganisationService();

            using (orgService as IDisposable)
            {
                var query = new QueryExpression("contact");
                query.ColumnSet.AddColumn("firstname");
                query.ColumnSet.AddColumn("lastname");

                // so link in customer address.
                query.AddLink("customeraddress", "contactid", "parentid", JoinOperator.Inner);
                var addressLink = query.LinkEntities[0];
                addressLink.EntityAlias = "A";
                addressLink.IncludeAllColumns();

                // conditions for max planck
                var firstName1Condition = new ConditionExpression("firstname", ConditionOperator.Equal, "Max");
                var lastname1Condition  = new ConditionExpression("lastname", ConditionOperator.Equal, "Planck");

                // Groups those conditions using an "AND" conjunction.
                var maxPlankFilter = new FilterExpression(LogicalOperator.And);
                maxPlankFilter.AddCondition(firstName1Condition);
                maxPlankFilter.AddCondition(lastname1Condition);

                // conditions for albert einstein
                var firstname2Condition = new ConditionExpression("firstname", ConditionOperator.Equal, "Albert");
                var lastname2Condition  = new ConditionExpression("lastname", ConditionOperator.Equal, "Einstein");

                // Groups those conditions using an "AND" conjunction.
                var albertEinsteinFilter = new FilterExpression(LogicalOperator.And);
                albertEinsteinFilter.AddCondition(firstname2Condition);
                albertEinsteinFilter.AddCondition(lastname2Condition);

                // could optionally chain the 2 filters so we get Albert's contitions chained (using AND) to max's conditions
                //  albertEinsteinFilter.AddFilter(maxPlankFilter);

                // conditions for address line 1 moonbase
                var addressLine1Filter = new FilterExpression(LogicalOperator.And); // dictates that this filter is chained to
                var line1Condition     = new ConditionExpression("A", "line1", ConditionOperator.Equal, "The secret moonbase");
                addressLine1Filter.AddCondition(line1Condition);


                // add filters to query
                // ensures each filter that we add to our queries criteria is chained together using an OR.
                query.Criteria.FilterOperator = LogicalOperator.Or;
                query.Criteria.AddFilter(albertEinsteinFilter);
                query.Criteria.AddFilter(maxPlankFilter);
                query.Criteria.AddFilter(addressLine1Filter);

                var results     = orgService.RetrieveMultiple(query);
                int resultCount = 0;
                foreach (var r in results.Entities)
                {
                    resultCount++;
                    Console.WriteLine(string.Format("{0} {1}", (string)r["firstname"], (string)r["lastname"]));
                }
                Console.WriteLine("There were " + resultCount + " results..");
            }
        }