项目作者: MarkMpn

项目描述 :
SQL 4 CDS core engine and XrmToolbox tool
高级语言: C#
项目地址: git://github.com/MarkMpn/Sql4Cds.git
创建时间: 2020-01-31T15:41:06Z
项目社区:https://github.com/MarkMpn/Sql4Cds

开源协议:MIT License

下载


SQL 4 CDS" class="reference-link"> SQL 4 CDS

By Mark Carrington, supported by Data8

SQL 4 CDS provides an engine,
XrmToolBox tool,
Azure Data Studio plugin
and SSMS plugin
for using standard SQL syntax to query data stored in Microsoft Dataverse / Dynamics 365.

It converts the provided SQL query into the corresponding FetchXML
syntax and allows the associated query to be executed, including the following types of query:

  • SELECT
  • INSERT
  • UPDATE
  • DELETE

For example:

  1. -- Get contact details
  2. SELECT c.firstname,
  3. c.lastname,
  4. a.telephone1
  5. FROM contact AS c
  6. INNER JOIN account AS a
  7. ON c.parentcustomerid = a.accountid
  8. WHERE c.firstname = 'Mark' AND
  9. a.statecode = 0
  10. ORDER BY c.createdon DESC
  11. -- Deactivate contacts without an email address
  12. UPDATE contact
  13. SET statecode = 1, statuscode = 2
  14. WHERE emailaddress1 IS NULL

✅ Although you are writing SQL, you are not directly running the queries against the back-end database. All data retrieval and
modification is done through the supported Dataverse API. Running an UPDATE/INSERT/DELETE command against the underlying SQL
database is unsafe, but the same query in SQL 4 CDS is translated to safe & supported API requests.

The engine converts all the SQL syntax that has a direct equivalent in FetchXML. It also attempts to support some more SQL features
that do not have an equivalent in FetchXML, such as calculated fields, HAVING clauses and more.

When executing a query it will take into account specific Dataverse features to improve the performance or results compared to
simply executing the FetchXML directly, e.g.:

  • Faster SELECT count(*) FROM entity query execution using RetrieveTotalRecordCountRequest
  • Automatically retrieving multiple pages of large result sets
  • Work around AggregateQueryRecordLimit errors by retrieving all the individual records and applying the aggregation in-memory.

As well as querying data with FetchXML, SQL 4 CDS can also query metadata by translating the SQL query into a
RetrieveMetadataChangesRequest or
RetrieveAllOptionSetsRequest:

  1. -- Find attributes without a description
  2. SELECT entity.logicalname,
  3. attribute.logicalname
  4. FROM metadata.entity
  5. INNER JOIN metadata.attribute
  6. ON entity.logicalname = attribute.entitylogicalname
  7. WHERE attribute.description IS NULL

You can also execute messages using stored procedure or table valued function syntax:

  1. -- Execute the WhoAmI message as a stored procedure. Capture the output parameters in variables
  2. declare @orgid uniqueidentifier, @buid uniqueidentifier, @userid uniqueidentifier
  3. exec WhoAmI @UserId = @userid output, @BusinessUnitId = @buid output, @OrganizationId = @orgid output
  4. -- Show the values of the variables
  5. select @userid, @orgid, @buid
  6. -- Execute the same message using table valued function syntax
  7. select * from WhoAmI()

FetchXML Builder Integration

As well as writing and executing queries as SQL, the generated FetchXML can be sent to FetchXML Builder
for further editing or converting to another syntax such as OData. You can also start building a query in FetchXML Builder and then edit
it in SQL 4 CDS.

Library Usage

The NuGet package includes assemblies for .NET Framework 4.6.2 and later, and .NET Core 3.1 and later.

You can use it in the same way as a SQL Server connection, using Sql4CdsConnection instead of SqlConnection:

  1. using (var con = new Sql4CdsConnection(connectionString))
  2. using (var cmd = con.CreateCommand())
  3. {
  4. cmd.CommandText = "INSERT INTO account (name) VALUES (@name)";
  5. var nameParam = cmd.CreateParameter();
  6. nameParam.Name = "@name";
  7. nameParam.Value = "My New Account";
  8. cmd.Parameters.Add(nameParam);
  9. // Add the new account
  10. cmd.ExecuteNonQuery();
  11. // Get the IDs of all accounts with the same name
  12. cmd.CommandText = "SELECT accountid FROM account WHERE name = @name";
  13. using (var reader = cmd.ExecuteReader())
  14. {
  15. while (reader.Read())
  16. {
  17. var accountId = reader.GetGuid(0);
  18. Console.WriteLine(accountId.ToString());
  19. }
  20. }
  21. }

The connection string should be any standard XRM connection string.

If you already have an IOrganizationService connection to the instance you want to use, you can pass that to the
constructor instead of the connection string.

You can also connect to multiple instances at once and execute queries to combine or copy data between them. To use this,
pass all the IOrganizationService instances to the Sql4CdsConnection constructor. You can then reference
data from a specific instance using instancename.dbo.tablename.

Advanced Options

There are various properties available on the Sql4CdsConnection class that you can use to control exactly how your queries are executed:

Property Description
BatchSize When executing DML operations, how many requests should be sent to the server at once?
BypassCustomPlugins When executing DML operations, should custom plugins be bypassed?
UseLocalTimeZone When working with date values, this property indicates whether the local or UTC time zone should be used.
MaxDegreeOfParallelism How many requests can be made in parallel? Currently used for DML and partitioned aggregate queries.
UseTDSEndpoint Indicates if the preview TDS Endpoint should be used where possible to execute SELECT queries.
BlockDeleteWithoutWhere Indicates if an error should be produced if running a DELETE query without a corresponding WHERE clause.
BlockUpdateWithoutWhere Indicates if an error should be produced if running a UPDATE query without a corresponding WHERE clause.
UseBulkDelete Set to true to use a bulk delete job instead of deleting individual records for a DELETE query.
ReturnEntityReferenceAsGuid Indicates if lookup values should be returned as simple Guid values rather than the default SqlEntityReference type.
UseRetrieveTotalRecordCount Indicates if a RetrieveTotalRecordCountRequest request should be used for simple COUNT(*) queries. This lets the query run faster but may produce out-of-date results.
QuotedIdentifiers Indicates if " can be used to quote identifiers such as column and table names. Equivalent to SET QUOTED_IDENTIFIERS ON.

There are also events that you can attach to to receive notifications while a query is executing. The InfoMessage and StatementCompleted events follow the pattern
provided by the SqlClient classes for SQL Server, but add extra data specific to SQL 4 CDS.

Event Description
PreDelete
PreInsert
PreUpdate
These events on the connection are raised just before an INSERT/DELETE/UPDATE command is about to be executed. The event argument includes the metadata of the entity type that will be affected along with the number of rows. The event handler can prevent the operation by setting the Cancel property of the event argument to true. Cancelling the operation will also cancel the entire batch.
PreRetrieve This event on the connection is raised just before more data is about to be retrieved from the server. The event argument contains the number of rows already retrieved so far. The event handler can prevent the retrieval from continuing by setting the Cancel property of the event argument to true. Cancelling a data retrieval will not cancel the entire batch, but will cause it to operate only on partial results.
Progress This event on the connection is raised when there is some update to the internal progress of executing a query, and can be used to provide feedback to the user that their query is progressing.
InfoMessage This event on the connection is raised when there is some textual output from the query available.
StatementCompleted This event on the command is raised when a statement within the current query has completed successfully. The event arguments show the number of records that were affected by the query as well as the details of the internal query plan that was executed for the statement.