This is an automated email from the ASF dual-hosted git repository.
ptupitsyn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new e715e530f8 IGNITE-18948 .NET: Add README for NuGet package (#1878)
e715e530f8 is described below
commit e715e530f8362df464d15a5aa9c0581d8fbc3012
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Mon Apr 3 07:43:25 2023 +0300
IGNITE-18948 .NET: Add README for NuGet package (#1878)
Add a README to [make our NuGet page
nicer](https://devblogs.microsoft.com/nuget/write-a-high-quality-readme-for-nuget-packages/).
Nightly version uploaded:
https://www.nuget.org/packages/Apache.Ignite/3.0.0-nightly20230332#readme-body-tab
The same README will appear on the GitHub page in .NET directory:
https://github.com/apache/ignite-3/tree/main/modules/platforms/dotnet
---
.../dotnet/Apache.Ignite/Apache.Ignite.csproj | 5 +
modules/platforms/dotnet/README.md | 266 ++++++++++++++++++++-
2 files changed, 270 insertions(+), 1 deletion(-)
diff --git a/modules/platforms/dotnet/Apache.Ignite/Apache.Ignite.csproj
b/modules/platforms/dotnet/Apache.Ignite/Apache.Ignite.csproj
index b06c7870fe..ec870711f7 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Apache.Ignite.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite/Apache.Ignite.csproj
@@ -25,6 +25,7 @@
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Apache.Ignite.snk</AssemblyOriginatorKeyFile>
<IsPackable>true</IsPackable>
+ <PackageReadmeFile>README.md</PackageReadmeFile>
<EmitCompilerGeneratedFiles>false</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
@@ -54,4 +55,8 @@
<ProjectReference
Include="..\Apache.Ignite.Internal.Generators\Apache.Ignite.Internal.Generators.csproj"
OutputItemType="Analyzer" ReferenceOutputAssembly="false"
SetTargetFramework="TargetFramework=netstandard2.0" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.md" Pack="true" PackagePath="\"/>
+ </ItemGroup>
+
</Project>
diff --git a/modules/platforms/dotnet/README.md
b/modules/platforms/dotnet/README.md
index 713fcee457..c48e566963 100644
--- a/modules/platforms/dotnet/README.md
+++ b/modules/platforms/dotnet/README.md
@@ -1,2 +1,266 @@
-# Apache Ignite 3 .NET Thin Client
+# Apache Ignite 3 .NET Client
+.NET client for [Apache Ignite](https://ignite.apache.org/) - a distributed
database for high‑performance applications with in‑memory speed.
+
+
+# Key Features
+
+* Full support of all Ignite APIs: SQL, Transactions, Key/Value, Compute.
+* Connects to any number of Ignite nodes at the same time.
+* Partition awareness: sends key-based requests to the right node.
+* Load-balancing, failover, automatic reconnection and request retries.
+* Built-in LINQ provider for strongly-typed SQL queries.
+* Integrates with [NodaTime](https://nodatime.org/) to provide precise mapping
to Ignite date/time types.
+* Logging and metrics.
+* High performance and fully asynchronous.
+
+
+# Getting Started
+
+Below are a few examples of basic usage to get you started:
+
+```cs
+// Connect to the cluster.
+var cfg = new IgniteClientConfiguration("127.0.0.1:10800");
+IIgniteClient client = await IgniteClient.StartAsync(cfg);
+
+// Start a read-only transaction.
+await using var tx = await client.Transactions.BeginAsync(
+ new TransactionOptions { ReadOnly = true });
+
+// Get table by name.
+ITable? table = await client.Tables.GetTableAsync("Person");
+
+// Get a strongly-typed view of table data using Person record.
+IRecordView<Person> view = table!.GetRecordView<Person>();
+
+// Upsert a record with KV (NoSQL) API.
+await view.UpsertAsync(tx, new Person(1, "John"));
+
+// Query data with SQL.
+await using var resultSet = await client.Sql.ExecuteAsync<Person>(
+ tx, "SELECT * FROM Person");
+
+List<Person> sqlResults = await resultSet.ToListAsync();
+
+// Query data with LINQ.
+List<string> names = view.AsQueryable(tx)
+ .OrderBy(person => person.Name)
+ .Select(person => person.Name)
+ .ToList();
+
+// Execute a distributed computation.
+IList<IClusterNode> nodes = await client.GetClusterNodesAsync();
+int wordCount = await client.Compute.ExecuteAsync<int>(
+ nodes, "org.foo.bar.WordCountTask", "Hello, world!");
+```
+
+# API Walkthrough
+
+## Configuration
+
+`IgniteClientConfiguration` is used to configure connections properties
(endpoints, SSL), retry policy, logging, and timeouts.
+
+```cs
+var cfg = new IgniteClientConfiguration
+{
+ // Connect to multiple servers.
+ Endpoints = { "server1:10800", "server2:10801" },
+
+ // Enable TLS.
+ SslStreamFactory = new SslStreamFactory
+ {
+ SslClientAuthenticationOptions = new SslClientAuthenticationOptions
+ {
+ // Allow self-signed certificates.
+ RemoteCertificateValidationCallback =
+ (sender, certificate, chain, errors) => true
+ }
+ },
+
+ // Retry all read operations in case of network issues.
+ RetryPolicy = new RetryReadPolicy { RetryLimit = 32 },
+
+ // Log to console.
+ Logger = new ConsoleLogger { MinLevel = LogLevel.Debug }
+};
+```
+
+## SQL
+
+SQL is the primary API for data access. It is used to create, drop, and query
tables, as well as to insert, update, and delete data.
+
+```cs
+using var client = await IgniteClient.StartAsync(new("localhost"));
+
+await client.Sql.ExecuteAsync(
+ null, "CREATE TABLE Person (Id INT PRIMARY KEY, Name VARCHAR)");
+
+await client.Sql.ExecuteAsync(
+ null, "INSERT INTO Person (Id, Name) VALUES (1, 'John Doe')");
+
+await using var resultSet = await client.Sql.ExecuteAsync(
+ null, "SELECT Name FROM Person");
+
+await foreach (IIgniteTuple row in resultSet)
+ Console.WriteLine(row[0]);
+```
+
+### Mapping SQL Results to User Types
+
+SQL results can be mapped to user types using `ExecuteAsync<T>` method. This
is cleaner and more efficient than `IIgniteTuple` approach above.
+
+```cs
+await using var resultSet = await client.Sql.ExecuteAsync<Person>(
+ null, "SELECT Name FROM Person");
+
+await foreach (Person p in resultSet)
+ Console.WriteLine(p.Name);
+
+public record Person(int Id, string Name);
+```
+
+Column names are matched to record properties by name. To map columns to
properties with different names, use `ColumnAttribute`.
+
+## DbDataReader (ADO.NET API)
+
+Another way to work with query results is `System.Data.Common.DbDataReader`,
which can be obtained with `ExecuteReaderAsync` method.
+
+For example, you can bind query results to a `DataGridView` control:
+
+```cs
+await using var reader = await Client.Sql.ExecuteReaderAsync(
+ null, "select * from Person");
+
+var dt = new DataTable();
+dt.Load(reader);
+
+dataGridView1.DataSource = dt;
+```
+
+## NoSQL
+
+NoSQL API is used to store and retrieve data in a key/value fashion. It can be
more efficient than SQL in certain scenarios.
+Existing tables can be accessed, but new tables can only be created with SQL.
+
+First, get a table by name:
+
+```cs
+ITable? table = await client.Tables.GetTableAsync("Person");
+```
+
+Then, there are two ways to look at the data.
+
+### Record View
+
+Record view represents the entire row as a single object. It can be an
`IIgniteTuple` or a user-defined type.
+
+```cs
+IRecordView<IIgniteTuple> binaryView = table.RecordBinaryView;
+IRecordView<Person> view = table.GetRecordView<Person>();
+
+await view.UpsertAsync(null, new Person(1, "John"));
+```
+
+### KeyValue View
+
+Key/Value view splits the row into key and value parts.
+
+```cs
+IKeyValueView<IIgniteTuple, IIgniteTuple> kvBinaryView =
table.KeyValueBinaryView;
+IKeyValueView<PersonKey, Person> kvView = table.GetKeyValueView<PersonKey,
Person>();
+
+await kvView.PutAsync(null, new PersonKey(1), new Person("John"));
+```
+
+
+## LINQ
+
+Data can be queried and modified with LINQ using `AsQueryable` method.
+LINQ expressions are translated to SQL queries and executed on the server.
+
+```cs
+ITable? table = await client.Tables.GetTableAsync("Person");
+IRecordView<Person> view = table!.GetRecordView<Person>();
+
+IQueryable<string> query = view.AsQueryable()
+ .Where(p => p.Id > 100)
+ .Select(p => p.Name);
+
+List<string> names = await query.ToListAsync();
+```
+
+Generated SQL can be retrieved with `ToQueryString` extension method, or by
enabling debug logging.
+
+Bulk update and delete with optional conditions are supported via
`ExecuteUpdateAsync` and `ExecuteDeleteAsync` extensions methods on
`IQueryable<T>`
+
+
+## Transactions
+
+All operations on data in Ignite are transactional. If a transaction is not
specified, an explicit transaction is started and committed automatically.
+
+To start a transaction, use `ITransactions.BeginAsync` method. Then, pass the
transaction object to all operations that should be part of the same
transaction.
+
+```cs
+ITransaction tx = await client.Transactions.BeginAsync();
+
+await view.UpsertAsync(tx, new Person(1, "John"));
+
+await client.Sql.ExecuteAsync(
+ tx, "INSERT INTO Person (Id, Name) VALUES (2, 'Jane')");
+
+await view.AsQueryable(tx)
+ .Where(p => p.Id > 0)
+ .ExecuteUpdateAsync(p => new Person(p.Id, p.Name + " Doe"));
+
+await tx.CommitAsync();
+```
+
+
+## Compute
+
+Compute API is used to execute distributed computations on the cluster.
Compute jobs should be implemented in Java, deployed to server nodes, and
called by the full class name.
+
+```cs
+IList<IClusterNode> nodes = await client.GetClusterNodesAsync();
+string result = await client.Compute.ExecuteAsync<string>(
+ nodes, "org.acme.tasks.MyTask", "Task argument 1", "Task argument 2");
+```
+
+
+## Failover, Retry, Reconnect, Load Balancing
+
+Ignite client implements a number of features to improve reliability and
performance:
+* When multiple endpoints are configured, the client will maintain connections
to all of them, and load balance requests between them.
+* If a connection is lost, the client will try to reconnect, assuming it may
be a temporary network issue or a node restart.
+* Periodic heartbeat messages are used to detect connection issues early.
+* If a user request fails due to a connection issue, the client will retry it
automatically according to the configured
`IgniteClientConfiguration.RetryPolicy`.
+
+
+## Logging
+
+To enable logging, set `IgniteClientConfiguration.Logger` property.
`ConsoleLogger` is provided out of the box. Other loggers can be integrated by
implementing `IIgniteLogger` interface.
+
+
+## Metrics
+
+Ignite client exposes a number of metrics with `Apache.Ignite` meter name
through the [System.Diagnostics.Metrics
API](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/metrics-instrumentation)
+that can be used to monitor system health and performance.
+
+For example,
[dotnet-counters](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters)
tool can be used like this:
+
+```sh
+dotnet-counters monitor --counters Apache.Ignite,System.Runtime --process-id
PID
+```
+
+# Documentation
+
+Full documentation is available at https://ignite.apache.org/docs.
+
+# Feedback
+
+Use any of the following channels to provide feedback:
+
+* [[email protected]](mailto:[email protected])
+* https://stackoverflow.com/questions/tagged/ignite
+* https://github.com/apache/ignite-3/issues