Skip to content

Commit 9625a8a

Browse files
committed
add sample article
1 parent d8acf2d commit 9625a8a

File tree

2 files changed

+245
-0
lines changed
  • powerapps-docs/developer/data-platform/org-service

2 files changed

+245
-0
lines changed

powerapps-docs/developer/data-platform/org-service/TOC.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
- name: Optimize performance
5454
displayName: Optimize performance using QueryExpression
5555
href: queryexpression/optimize-performance.md
56+
- name: Sample code
57+
displayName: QueryExpression, Sample code
58+
href: queryexpression/sample.md
5659
- name: Use the QueryByAttribute class
5760
href: use-querybyattribute-class.md
5861
- name: Create table rows
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
---
2+
title: QueryExpression Sample code
3+
description: Try using QueryExpression to retrieve Dataverse data using this sample code.
4+
ms.date: 05/17/2024
5+
ms.reviewer: jdaly
6+
ms.topic: how-to
7+
author: pnghub
8+
ms.subservice: dataverse-developer
9+
ms.author: gned
10+
search.audienceType:
11+
- developer
12+
contributors:
13+
- JimDaly
14+
- dmitmikh
15+
- dasussMS
16+
---
17+
# QueryExpression sample code
18+
19+
To try using QueryExpression with C#, you can use the `OutputQueryExpression` static method in this article by adapting the [Quick Start: Execute an SDK for .NET request (C#)](../org-service/quick-start-org-service-console-app.md)
20+
21+
> [!NOTE]
22+
> See [Paging Cookie example](page-results.md#paging-cookie-example) for sample code to retrieve data in pages.
23+
24+
You can use the following `OutputFetchRequest` static method to test FetchXml queries in a console application.
25+
26+
The `OutputQueryExpression` method demonstrates how to use the [QueryExpression class](xref:Microsoft.Xrm.Sdk.Query.QueryExpression) and the [IOrganizationService.RetrieveMultiple method](xref:Microsoft.Xrm.Sdk.IOrganizationService.RetrieveMultiple%2A) to return an [EntityCollection](xref:Microsoft.Xrm.Sdk.EntityCollection) containing the requested data.
27+
28+
The `OutputQueryExpression` method depends on the [ConsoleTables NuGet package](https://www.nuget.org/packages/ConsoleTables/2.5.0) and requires that all [entity](reference/entity.md) or [link-entity](reference/link-entity.md) element [attribute elements](reference/attribute.md) are included, which is a best practice.
29+
30+
```csharp
31+
/// <summary>
32+
/// Renders the output of a query in a table for a console application
33+
/// </summary>
34+
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
35+
/// <param name="query">The query to use</param>
36+
/// <exception cref="Exception">
37+
/// OutputQueryExpression requires all LinkEntity instances that contain columns specify an EntityAlias property.
38+
/// </exception>
39+
static void OutputQueryExpression(IOrganizationService service, QueryExpression query)
40+
{
41+
//Retrieve the data
42+
EntityCollection entityCollection = service.RetrieveMultiple(query: query);
43+
44+
//Get column names from the query
45+
var columns = GetQueryExpressionColumns(query);
46+
47+
// Create the table using https://www.nuget.org/packages/ConsoleTables/2.5.0
48+
var table = new ConsoleTables.ConsoleTable(columns.ToArray());
49+
50+
// Add the rows of the table
51+
entityCollection.Entities.ToList().ForEach(entity =>
52+
{
53+
table.Rows.Add(GetRowValues(columns, entity).ToArray());
54+
});
55+
56+
// Write the table to the console
57+
table.Write();
58+
59+
// Get a list of column names from the query
60+
List<string> GetQueryExpressionColumns(QueryExpression query)
61+
{
62+
List<string> columns = new();
63+
64+
columns.AddRange(GetColumns(query.ColumnSet));
65+
66+
foreach (LinkEntity linkEntity in query.LinkEntities)
67+
{
68+
columns.AddRange(GetLinkEntityColumns(linkEntity));
69+
}
70+
71+
return columns;
72+
}
73+
74+
// Get column names from any linked tables
75+
List<string> GetLinkEntityColumns(LinkEntity linkEntity)
76+
{
77+
if (string.IsNullOrWhiteSpace(linkEntity.EntityAlias))
78+
{
79+
if (linkEntity.Columns.Columns.Count != 0)
80+
{
81+
string message = "OutputQueryExpressionRequest requires all ";
82+
message += "LinkEntity instances that contain columns ";
83+
message += "specify an EntityAlias property.";
84+
85+
throw new Exception(message);
86+
}
87+
}
88+
89+
List<string> columns = new();
90+
91+
columns.AddRange(GetColumns(linkEntity.Columns, linkEntity.EntityAlias));
92+
93+
foreach (LinkEntity le in linkEntity.LinkEntities)
94+
{
95+
columns.AddRange(GetColumns(le.Columns, le.EntityAlias));
96+
}
97+
return columns;
98+
}
99+
100+
// Get columns from a columnset
101+
List<string> GetColumns(ColumnSet columnset, string alias = null)
102+
{
103+
List<string> columns = new();
104+
105+
foreach (string column in columnset.Columns)
106+
{
107+
columns.Add(string.IsNullOrWhiteSpace(alias) ? column : $"{alias}.{column}");
108+
}
109+
110+
foreach (XrmAttributeExpression item in columnset.AttributeExpressions)
111+
{
112+
columns.Add(item.Alias ?? item.AttributeName);
113+
}
114+
115+
return columns;
116+
}
117+
118+
// Get the values of a row as strings
119+
List<string> GetRowValues(List<string> columns, Entity entity)
120+
{
121+
List<string> values = new();
122+
columns.ForEach(column =>
123+
{
124+
if (entity.Attributes.ContainsKey(column))
125+
{
126+
// Use the formatted value if it available
127+
if (entity.FormattedValues.ContainsKey(column))
128+
{
129+
values.Add($"{entity.FormattedValues[column]}");
130+
}
131+
else
132+
{
133+
// When an alias is used, the Aliased value must be converted
134+
if (entity.Attributes[column] is AliasedValue aliasedValue)
135+
{
136+
// When an EntityReference doesn't have a Name, show the Id
137+
if (aliasedValue.Value is EntityReference lookup &&
138+
string.IsNullOrWhiteSpace(lookup.Name))
139+
{
140+
values.Add($"{lookup.Id:B}");
141+
}
142+
else
143+
{
144+
values.Add($"{aliasedValue.Value}");
145+
}
146+
}
147+
else
148+
{
149+
// Use the simple attribute value
150+
values.Add($"{entity.Attributes[column]}");
151+
}
152+
}
153+
}
154+
// Null values are not in the Attributes collection
155+
else
156+
{
157+
values.Add("NULL");
158+
}
159+
160+
});
161+
return values;
162+
}
163+
}
164+
```
165+
166+
### Update SDK for .NET quick start sample
167+
168+
You can adapt the [Quick Start: Execute an SDK for .NET request (C#)](../org-service/quick-start-org-service-console-app.md) sample to test queries with the following steps:
169+
170+
1. Install the [ConsoleTables NuGet package](https://www.nuget.org/packages/ConsoleTables/2.5.0)
171+
1. Add the following using statements at the top of the `program.cs` file
172+
173+
```csharp
174+
using Microsoft.Xrm.Sdk;
175+
using Microsoft.Xrm.Sdk.Query;
176+
using System.Text;
177+
using System.Xml.Linq;
178+
```
179+
180+
1. Copy and paste the `OutputQueryExpression` method below the `Main` method.
181+
1. Edit the `Main` method to set your query and use the `OutputQueryExpression` method.
182+
183+
```csharp
184+
static void Main(string[] args)
185+
{
186+
using (ServiceClient serviceClient = new(connectionString))
187+
{
188+
if (serviceClient.IsReady)
189+
{
190+
//WhoAmIResponse response =
191+
// (WhoAmIResponse)serviceClient.Execute(new WhoAmIRequest());
192+
193+
//Console.WriteLine("User ID is {0}.", response.UserId);
194+
195+
QueryExpression query = new("account")
196+
{
197+
TopCount = 5,
198+
ColumnSet = new ColumnSet(
199+
"accountclassificationcode",
200+
"createdby",
201+
"createdon",
202+
"name")
203+
};
204+
205+
OutputQueryExpression(serviceClient, query);
206+
}
207+
else
208+
{
209+
Console.WriteLine(
210+
"A web service connection was not established.");
211+
}
212+
}
213+
214+
// Pause the console so it does not close.
215+
Console.WriteLine("Press the <Enter> key to exit.");
216+
Console.ReadLine();
217+
}
218+
```
219+
220+
When you run the program using the `OutputQueryExpression` method, the output should look like this:
221+
222+
```text
223+
---------------------------------------------------------------------------------------------------------
224+
| accountclassificationcode | createdby | createdon | name |
225+
---------------------------------------------------------------------------------------------------------
226+
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | Litware, Inc. (sample) |
227+
---------------------------------------------------------------------------------------------------------
228+
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | Adventure Works (sample) |
229+
---------------------------------------------------------------------------------------------------------
230+
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | Fabrikam, Inc. (sample) |
231+
---------------------------------------------------------------------------------------------------------
232+
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | Blue Yonder Airlines (sample) |
233+
---------------------------------------------------------------------------------------------------------
234+
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | City Power & Light (sample) |
235+
---------------------------------------------------------------------------------------------------------
236+
```
237+
238+
### Related articles
239+
240+
[Query data using QueryExpression](overview.md)
241+
[Sample: Retrieve multiple with the QueryExpression class](../samples/retrieve-multiple-queryexpression-class.md)
242+
[Sample: Use QueryExpression with a paging cookie](../samples/use-queryexpression-with-a-paging-cookie.md)

0 commit comments

Comments
 (0)