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 3f7cf62a253 IGNITE-27265 .NET: Improve partition API (#7467)
3f7cf62a253 is described below

commit 3f7cf62a2533c8561b88868ebf52964af7abc1a6
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Fri Jan 23 16:20:49 2026 +0200

    IGNITE-27265 .NET: Improve partition API (#7467)
    
    * Deprecate `IPartitionManager`, replace with `IPartitionDistribution`
    * Add `GetPartitionsAsync()` and `GetPrimaryReplicasAsync(IClusterNode 
node)`
    * Add `IPartition.Id`
---
 .../CurrentClientWithOldServerCompatibilityTest.cs |  2 +-
 .../dotnet/Apache.Ignite.Tests/FakeServer.cs       |  4 +-
 ...nagerTests.cs => PartitionDistributionTests.cs} | 75 ++++++++++++++++------
 .../Table/PartitionManagerTests.cs                 | 14 ++--
 .../Apache.Ignite/ApiCompatibilitySuppressions.xml | 14 ++++
 .../dotnet/Apache.Ignite/ClientOperationType.cs    |  2 +-
 .../Apache.Ignite/Internal/Table/DataStreamer.cs   | 10 +--
 .../Internal/Table/DataStreamerWithReceiver.cs     |  8 +--
 .../Apache.Ignite/Internal/Table/HashPartition.cs  |  4 +-
 .../Internal/Table/PartitionManager.cs             | 47 ++++++++++++--
 .../dotnet/Apache.Ignite/Internal/Table/Table.cs   |  4 +-
 .../dotnet/Apache.Ignite/Table/IPartition.cs       |  6 +-
 ...rtitionManager.cs => IPartitionDistribution.cs} | 26 ++++++--
 .../Apache.Ignite/Table/IPartitionManager.cs       |  6 +-
 .../platforms/dotnet/Apache.Ignite/Table/ITable.cs |  9 ++-
 15 files changed, 173 insertions(+), 58 deletions(-)

diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Tests/Compatibility/CurrentClientWithOldServerCompatibilityTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Tests/Compatibility/CurrentClientWithOldServerCompatibilityTest.cs
index 3863ef2d64c..818b38b882b 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Tests/Compatibility/CurrentClientWithOldServerCompatibilityTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Tests/Compatibility/CurrentClientWithOldServerCompatibilityTest.cs
@@ -139,7 +139,7 @@ public class CurrentClientWithOldServerCompatibilityTest
         ITable? table = await _client.Tables.GetTableAsync(TableNameTest);
         Assert.IsNotNull(table);
 
-        IReadOnlyDictionary<IPartition, IClusterNode> primaryReplicas = await 
table.PartitionManager.GetPrimaryReplicasAsync();
+        IReadOnlyDictionary<IPartition, IClusterNode> primaryReplicas = await 
table.PartitionDistribution.GetPrimaryReplicasAsync();
         Assert.AreEqual(25, primaryReplicas.Count);
 
         var clusterNode = _client.GetConnections().Select(x => x.Node).First();
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs
index 789a045a4b2..aa2f757b8ad 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs
@@ -402,7 +402,7 @@ namespace Apache.Ignite.Tests
                     case ClientOp.StreamerWithReceiverBatchSend:
                     {
                         reader.ReadInt32(); // table
-                        reader.ReadInt32(); // partition
+                        reader.ReadInt64(); // partition
                         var unitCount = reader.ReadInt32();
                         reader.Skip(unitCount);
                         reader.ReadBoolean(); // returnResults.
@@ -431,7 +431,7 @@ namespace Apache.Ignite.Tests
                         {
                             var nodeId = PartitionAssignment[index];
 
-                            writer.Write(index); // Partition id.
+                            writer.Write((long)index); // Partition id.
                             writer.Write(4); // Prop count.
                             writer.Write(Guid.NewGuid()); // Id.
                             writer.Write(nodeId); // Name.
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionManagerTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionDistributionTests.cs
similarity index 67%
copy from 
modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionManagerTests.cs
copy to 
modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionDistributionTests.cs
index 5797a5dac2a..7b52f5b41f3 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionManagerTests.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionDistributionTests.cs
@@ -24,24 +24,24 @@ using System.Net;
 using System.Threading.Tasks;
 using Common.Compute;
 using Common.Table;
-using Compute;
 using Ignite.Compute;
 using Ignite.Table;
 using Internal.Table;
+using Network;
 using NUnit.Framework;
 using static Common.Table.TestTables;
 
 /// <summary>
-/// Tests for <see cref="IPartitionManager"/>.
+/// Tests for <see cref="IPartitionDistribution"/>.
 /// </summary>
-public class PartitionManagerTests : IgniteTestsBase
+public class PartitionDistributionTests : IgniteTestsBase
 {
     [Test]
     public async Task TestGetPrimaryReplicas()
     {
-        var replicas = await Table.PartitionManager.GetPrimaryReplicasAsync();
+        var replicas = await 
Table.PartitionDistribution.GetPrimaryReplicasAsync();
         var replicasNodes = replicas.Values.Distinct().OrderBy(x => 
((IPEndPoint)x.Address).Port).ToList();
-        var replicasPartitions = replicas.Keys.Select(x => 
((HashPartition)x).PartitionId).OrderBy(x => x).ToList();
+        var replicasPartitions = replicas.Keys.Select(x => 
((HashPartition)x).Id).OrderBy(x => x).ToList();
 
         var expectedNodes = (await Client.GetClusterNodesAsync())
             .OrderBy(x => ((IPEndPoint)x.Address).Port)
@@ -68,8 +68,8 @@ public class PartitionManagerTests : IgniteTestsBase
 
         async Task<List<HashPartition>> GetPartitions()
         {
-            var replicas = await 
Table.PartitionManager.GetPrimaryReplicasAsync();
-            return replicas.Keys.Cast<HashPartition>().OrderBy(x => 
x.PartitionId).ToList();
+            var replicas = await 
Table.PartitionDistribution.GetPrimaryReplicasAsync();
+            return replicas.Keys.Cast<HashPartition>().OrderBy(x => 
x.Id).ToList();
         }
     }
 
@@ -81,7 +81,7 @@ public class PartitionManagerTests : IgniteTestsBase
         for (int partId = 0; partId < TablePartitionCount; partId++)
         {
             var partition = new HashPartition(partId);
-            var replica = await 
Table.PartitionManager.GetPrimaryReplicaAsync(partition);
+            var replica = await 
Table.PartitionDistribution.GetPrimaryReplicaAsync(partition);
 
             CollectionAssert.Contains(nodes, replica);
         }
@@ -91,25 +91,25 @@ public class PartitionManagerTests : IgniteTestsBase
     public void TestGetPrimaryReplicaNegativePartitionIdThrows()
     {
         var ex = Assert.ThrowsAsync<ArgumentException>(
-            async () => await 
Table.PartitionManager.GetPrimaryReplicaAsync(new HashPartition(-1)));
+            async () => await 
Table.PartitionDistribution.GetPrimaryReplicaAsync(new HashPartition(-1)));
 
-        Assert.AreEqual("Partition id can't be negative: HashPartition { 
PartitionId = -1 }", ex.Message);
+        Assert.AreEqual("Partition id can't be negative: HashPartition { Id = 
-1 }", ex.Message);
     }
 
     [Test]
     public void TestGetPrimaryReplicaPartitionIdOutOfRangeThrows()
     {
         var ex = Assert.ThrowsAsync<ArgumentException>(
-            async () => await 
Table.PartitionManager.GetPrimaryReplicaAsync(new HashPartition(10)));
+            async () => await 
Table.PartitionDistribution.GetPrimaryReplicaAsync(new HashPartition(10)));
 
-        Assert.AreEqual("Partition id can't be greater than 9: HashPartition { 
PartitionId = 10 }", ex.Message);
+        Assert.AreEqual("Partition id can't be greater than 9: HashPartition { 
Id = 10 }", ex.Message);
     }
 
     [Test]
     public void TestGetPrimaryReplicaUnknownPartitionClassThrows()
     {
         var ex = Assert.ThrowsAsync<ArgumentException>(
-            async () => await 
Table.PartitionManager.GetPrimaryReplicaAsync(new MyPartition()));
+            async () => await 
Table.PartitionDistribution.GetPrimaryReplicaAsync(new MyPartition()));
 
         Assert.AreEqual($"Unsupported partition type: {typeof(MyPartition)}", 
ex.Message);
     }
@@ -123,22 +123,22 @@ public class PartitionManagerTests : IgniteTestsBase
         {
             var partition = poco
                 ? withMapper
-                    ? await 
Table.PartitionManager.GetPartitionAsync(GetPoco(id), new PocoMapper())
-                    : await 
Table.PartitionManager.GetPartitionAsync(GetPoco(id))
-                : await Table.PartitionManager.GetPartitionAsync(GetTuple(id));
+                    ? await 
Table.PartitionDistribution.GetPartitionAsync(GetPoco(id), new PocoMapper())
+                    : await 
Table.PartitionDistribution.GetPartitionAsync(GetPoco(id))
+                : await 
Table.PartitionDistribution.GetPartitionAsync(GetTuple(id));
 
             var partitionJobExec = await Client.Compute.SubmitAsync(jobTarget, 
JavaJobs.PartitionJob, id);
             var expectedPartition = await partitionJobExec.GetResultAsync();
 
-            Assert.AreEqual(expectedPartition, 
((HashPartition)partition).PartitionId);
+            Assert.AreEqual(expectedPartition, ((HashPartition)partition).Id);
         }
     }
 
     [Test]
     public async Task TestGetPartitionReturnsCachedInstance()
     {
-        var partition1 = await 
Table.PartitionManager.GetPartitionAsync(GetTuple(1));
-        var partition2 = await 
Table.PartitionManager.GetPartitionAsync(GetTuple(1));
+        var partition1 = await 
Table.PartitionDistribution.GetPartitionAsync(GetTuple(1));
+        var partition2 = await 
Table.PartitionDistribution.GetPartitionAsync(GetTuple(1));
 
         Assert.AreSame(partition1, partition2);
     }
@@ -156,7 +156,7 @@ public class PartitionManagerTests : IgniteTestsBase
         var table = await 
client.Tables.GetTableAsync(FakeServer.ExistingTableName);
         var partition = new HashPartition(0);
 
-        var replica1 = await 
table!.PartitionManager.GetPrimaryReplicaAsync(partition);
+        var replica1 = await 
table!.PartitionDistribution.GetPrimaryReplicaAsync(partition);
         Assert.AreEqual("n1", replica1.Name);
 
         server.PartitionAssignmentTimestamp = 124;
@@ -164,7 +164,7 @@ public class PartitionManagerTests : IgniteTestsBase
 
         await client.Tables.GetTablesAsync(); // Trigger cache invalidation 
with any response.
 
-        var replica2 = await 
table.PartitionManager.GetPrimaryReplicaAsync(partition);
+        var replica2 = await 
table.PartitionDistribution.GetPrimaryReplicaAsync(partition);
         Assert.AreEqual("n2", replica2.Name);
     }
 
@@ -181,8 +181,41 @@ public class PartitionManagerTests : IgniteTestsBase
         Assert.IsFalse(part1.Equals(customPart));
     }
 
+    [Test]
+    public async Task TestGetPartitionsAsync()
+    {
+        IReadOnlyList<IPartition> partitions = await 
Table.PartitionDistribution.GetPartitionsAsync();
+
+        Assert.AreEqual(TablePartitionCount, partitions.Count);
+
+        for (int i = 0; i < TablePartitionCount; i++)
+        {
+            Assert.AreEqual(i, partitions[i].Id);
+        }
+    }
+
+    [Test]
+    public async Task TestGetPrimaryReplicasForNodeAsync()
+    {
+        IReadOnlyDictionary<IPartition, IClusterNode> allReplicas = await 
Table.PartitionDistribution.GetPrimaryReplicasAsync();
+
+        IList<IClusterNode> nodes = await Client.GetClusterNodesAsync();
+        IClusterNode node = nodes.First();
+        IReadOnlyList<IPartition> nodePartitions = await 
Table.PartitionDistribution.GetPrimaryReplicasAsync(node);
+
+        Assert.IsNotEmpty(nodePartitions);
+
+        foreach (var partition in nodePartitions)
+        {
+            Assert.IsTrue(allReplicas.TryGetValue(partition, out var 
replicaNode));
+            Assert.AreEqual(node.Name, replicaNode!.Name);
+        }
+    }
+
     private class MyPartition : IPartition
     {
+        public long Id => 999;
+
         public bool Equals(IPartition? other) => false;
     }
 }
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionManagerTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionManagerTests.cs
index 5797a5dac2a..8ec0aa0df28 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionManagerTests.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Tests/Table/PartitionManagerTests.cs
@@ -24,7 +24,6 @@ using System.Net;
 using System.Threading.Tasks;
 using Common.Compute;
 using Common.Table;
-using Compute;
 using Ignite.Compute;
 using Ignite.Table;
 using Internal.Table;
@@ -34,6 +33,7 @@ using static Common.Table.TestTables;
 /// <summary>
 /// Tests for <see cref="IPartitionManager"/>.
 /// </summary>
+[Obsolete("Obsolete. Replaced by PartitionDistributionTests.")]
 public class PartitionManagerTests : IgniteTestsBase
 {
     [Test]
@@ -41,7 +41,7 @@ public class PartitionManagerTests : IgniteTestsBase
     {
         var replicas = await Table.PartitionManager.GetPrimaryReplicasAsync();
         var replicasNodes = replicas.Values.Distinct().OrderBy(x => 
((IPEndPoint)x.Address).Port).ToList();
-        var replicasPartitions = replicas.Keys.Select(x => 
((HashPartition)x).PartitionId).OrderBy(x => x).ToList();
+        var replicasPartitions = replicas.Keys.Select(x => 
((HashPartition)x).Id).OrderBy(x => x).ToList();
 
         var expectedNodes = (await Client.GetClusterNodesAsync())
             .OrderBy(x => ((IPEndPoint)x.Address).Port)
@@ -69,7 +69,7 @@ public class PartitionManagerTests : IgniteTestsBase
         async Task<List<HashPartition>> GetPartitions()
         {
             var replicas = await 
Table.PartitionManager.GetPrimaryReplicasAsync();
-            return replicas.Keys.Cast<HashPartition>().OrderBy(x => 
x.PartitionId).ToList();
+            return replicas.Keys.Cast<HashPartition>().OrderBy(x => 
x.Id).ToList();
         }
     }
 
@@ -93,7 +93,7 @@ public class PartitionManagerTests : IgniteTestsBase
         var ex = Assert.ThrowsAsync<ArgumentException>(
             async () => await 
Table.PartitionManager.GetPrimaryReplicaAsync(new HashPartition(-1)));
 
-        Assert.AreEqual("Partition id can't be negative: HashPartition { 
PartitionId = -1 }", ex.Message);
+        Assert.AreEqual("Partition id can't be negative: HashPartition { Id = 
-1 }", ex.Message);
     }
 
     [Test]
@@ -102,7 +102,7 @@ public class PartitionManagerTests : IgniteTestsBase
         var ex = Assert.ThrowsAsync<ArgumentException>(
             async () => await 
Table.PartitionManager.GetPrimaryReplicaAsync(new HashPartition(10)));
 
-        Assert.AreEqual("Partition id can't be greater than 9: HashPartition { 
PartitionId = 10 }", ex.Message);
+        Assert.AreEqual("Partition id can't be greater than 9: HashPartition { 
Id = 10 }", ex.Message);
     }
 
     [Test]
@@ -130,7 +130,7 @@ public class PartitionManagerTests : IgniteTestsBase
             var partitionJobExec = await Client.Compute.SubmitAsync(jobTarget, 
JavaJobs.PartitionJob, id);
             var expectedPartition = await partitionJobExec.GetResultAsync();
 
-            Assert.AreEqual(expectedPartition, 
((HashPartition)partition).PartitionId);
+            Assert.AreEqual(expectedPartition, ((HashPartition)partition).Id);
         }
     }
 
@@ -183,6 +183,8 @@ public class PartitionManagerTests : IgniteTestsBase
 
     private class MyPartition : IPartition
     {
+        public long Id => -1;
+
         public bool Equals(IPartition? other) => false;
     }
 }
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/ApiCompatibilitySuppressions.xml 
b/modules/platforms/dotnet/Apache.Ignite/ApiCompatibilitySuppressions.xml
index 34c321c6fb0..dc1796783ff 100644
--- a/modules/platforms/dotnet/Apache.Ignite/ApiCompatibilitySuppressions.xml
+++ b/modules/platforms/dotnet/Apache.Ignite/ApiCompatibilitySuppressions.xml
@@ -147,4 +147,18 @@
     <Right>lib/net8.0/Apache.Ignite.dll</Right>
     <IsBaselineSuppression>true</IsBaselineSuppression>
   </Suppression>
+  <Suppression>
+    <DiagnosticId>CP0006</DiagnosticId>
+    <Target>P:Apache.Ignite.Table.IPartition.Id</Target>
+    <Left>lib/net8.0/Apache.Ignite.dll</Left>
+    <Right>lib/net8.0/Apache.Ignite.dll</Right>
+    <IsBaselineSuppression>true</IsBaselineSuppression>
+  </Suppression>
+  <Suppression>
+    <DiagnosticId>CP0006</DiagnosticId>
+    <Target>P:Apache.Ignite.Table.ITable.PartitionDistribution</Target>
+    <Left>lib/net8.0/Apache.Ignite.dll</Left>
+    <Right>lib/net8.0/Apache.Ignite.dll</Right>
+    <IsBaselineSuppression>true</IsBaselineSuppression>
+  </Suppression>
 </Suppressions>
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite/ClientOperationType.cs 
b/modules/platforms/dotnet/Apache.Ignite/ClientOperationType.cs
index dd9b5317eb5..ad3917942db 100644
--- a/modules/platforms/dotnet/Apache.Ignite/ClientOperationType.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/ClientOperationType.cs
@@ -152,7 +152,7 @@ namespace Apache.Ignite
         ComputeChangePriority,
 
         /// <summary>
-        /// Get primary replicas (<see 
cref="IPartitionManager.GetPrimaryReplicasAsync"/>).
+        /// Get primary replicas (<see 
cref="IPartitionDistribution.GetPrimaryReplicasAsync()"/>).
         /// </summary>
         PrimaryReplicasGet,
 
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamer.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamer.cs
index 236155dac77..c46efe1d761 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamer.cs
@@ -295,7 +295,7 @@ internal static class DataStreamer
 
         async Task SendAndDisposeBufAsync(
             PooledArrayBuffer buf,
-            int partitionId,
+            long partitionId,
             Task oldTask,
             DataStreamerItem<T>[] items,
             int count,
@@ -449,7 +449,7 @@ internal static class DataStreamer
         buf.Advance(5); // Reserve count.
     }
 
-    private static void WriteBatchHeader(PooledArrayBuffer buf, int 
partitionId, Schema schema, int deletedSetReserveSize)
+    private static void WriteBatchHeader(PooledArrayBuffer buf, long 
partitionId, Schema schema, int deletedSetReserveSize)
     {
         var w = buf.MessageWriter;
 
@@ -509,7 +509,7 @@ internal static class DataStreamer
 
     private static void ReWriteBatch<T>(
         PooledArrayBuffer buf,
-        int partitionId,
+        long partitionId,
         Schema schema,
         ReadOnlySpan<DataStreamerItem<T>> items,
         IRecordSerializerHandler<T> writer)
@@ -585,14 +585,14 @@ internal static class DataStreamer
 
     private sealed record Batch<T>
     {
-        public Batch(int capacity, Schema schema, int partitionId)
+        public Batch(int capacity, Schema schema, long partitionId)
         {
             PartitionId = partitionId;
             Items = GetPool<T>().Rent(capacity);
             Schema = schema;
         }
 
-        public int PartitionId { get; }
+        public long PartitionId { get; }
 
         public PooledArrayBuffer Buffer { get; set; } = 
ProtoCommon.GetMessageWriter();
 
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamerWithReceiver.cs
 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamerWithReceiver.cs
index f5e78261b68..b28d09d03c3 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamerWithReceiver.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamerWithReceiver.cs
@@ -279,7 +279,7 @@ internal static class DataStreamerWithReceiver
         }
 
         async Task SendAndDisposeBufAsync(
-            int partitionId,
+            long partitionId,
             Task oldTask,
             TPayload[] items,
             TSource[] sourceItems,
@@ -382,7 +382,7 @@ internal static class DataStreamerWithReceiver
         void SerializeBatch(
             PooledArrayBuffer buf,
             ArraySegment<TPayload> items,
-            int partitionId)
+            long partitionId)
         {
             // T is one of the supported types (numbers, strings, etc).
             var w = buf.MessageWriter;
@@ -449,14 +449,14 @@ internal static class DataStreamerWithReceiver
 
     private sealed record Batch<TSource, TPayload>
     {
-        public Batch(int capacity, int partitionId)
+        public Batch(int capacity, long partitionId)
         {
             PartitionId = partitionId;
             Items = GetPool<TPayload>().Rent(capacity);
             SourceItems = GetPool<TSource>().Rent(capacity);
         }
 
-        public int PartitionId { get; }
+        public long PartitionId { get; }
 
         [SuppressMessage("Performance", "CA1819:Properties should not return 
arrays", Justification = "Private record")]
         public TSource[] SourceItems { get; set; }
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/HashPartition.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/HashPartition.cs
index e85c954cace..d5252a893cf 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/HashPartition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/HashPartition.cs
@@ -22,8 +22,8 @@ using Ignite.Table;
 /// <summary>
 /// Hash partition.
 /// </summary>
-/// <param name="PartitionId">Partition id.</param>
-internal sealed record HashPartition(int PartitionId) : IPartition // Not a 
struct to avoid interface boxing.
+/// <param name="Id">Partition id.</param>
+internal sealed record HashPartition(long Id) : IPartition // Not a struct to 
avoid interface boxing.
 {
     /// <inheritdoc/>
     public bool Equals(IPartition? other) =>
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/PartitionManager.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/PartitionManager.cs
index df91b5c5156..d6262bf5c06 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/PartitionManager.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/PartitionManager.cs
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+// ReSharper disable InheritdocInvalidUsage
 namespace Apache.Ignite.Internal.Table;
 
 using System;
@@ -34,7 +35,9 @@ using Serialization;
 /// <summary>
 /// Table partition manager.
 /// </summary>
-internal sealed class PartitionManager : IPartitionManager
+#pragma warning disable CS0618 // Type or member is obsolete
+internal sealed class PartitionManager : IPartitionDistribution, 
IPartitionManager
+#pragma warning restore CS0618 // Type or member is obsolete
 {
     private static readonly object PartitionsLock = new();
 
@@ -76,7 +79,7 @@ internal sealed class PartitionManager : IPartitionManager
             throw new ArgumentException("Unsupported partition type: " + 
partition.GetType());
         }
 
-        if (hashPartition.PartitionId < 0)
+        if (hashPartition.Id < 0)
         {
             throw new ArgumentException("Partition id can't be negative: " + 
partition);
         }
@@ -84,12 +87,12 @@ internal sealed class PartitionManager : IPartitionManager
         var replicas = await 
GetPrimaryReplicasInternalAsync().ConfigureAwait(false);
         var nodes = replicas.Nodes;
 
-        if (hashPartition.PartitionId >= nodes.Length)
+        if (hashPartition.Id >= nodes.Length)
         {
             throw new ArgumentException($"Partition id can't be greater than 
{nodes.Length - 1}: {partition}");
         }
 
-        return nodes[hashPartition.PartitionId];
+        return nodes[hashPartition.Id];
     }
 
     /// <inheritdoc/>
@@ -107,6 +110,40 @@ internal sealed class PartitionManager : IPartitionManager
         where TK : notnull =>
         GetPartitionInternalAsync(key, new 
MapperSerializerHandler<TK>(mapper));
 
+    /// <inheritdoc/>
+    public async ValueTask<IReadOnlyList<IPartition>> GetPartitionsAsync()
+    {
+        var replicas = await 
GetPrimaryReplicasInternalAsync().ConfigureAwait(false);
+        var partitionsCount = replicas.Nodes.Length;
+        var cached = GetCachedPartitionArray(partitionsCount);
+
+        return cached.Length == partitionsCount
+            ? cached
+            : cached[..partitionsCount];
+    }
+
+    /// <inheritdoc/>
+    public async ValueTask<IReadOnlyList<IPartition>> 
GetPrimaryReplicasAsync(IClusterNode node)
+    {
+        IgniteArgumentCheck.NotNull(node);
+
+        var replicas = await 
GetPrimaryReplicasInternalAsync().ConfigureAwait(false);
+        var result = new List<IPartition>();
+        var nodesByPartition = replicas.Nodes;
+        var partitions = GetCachedPartitionArray(nodesByPartition.Length);
+
+        for (var i = 0; i < nodesByPartition.Length; i++)
+        {
+            // Compare only by name (consistent id).
+            if (nodesByPartition[i].Name == node.Name)
+            {
+                result.Add(partitions[i]);
+            }
+        }
+
+        return result;
+    }
+
     /// <inheritdoc/>
     public override string ToString() =>
         new IgniteToStringBuilder(GetType())
@@ -165,7 +202,7 @@ internal sealed class PartitionManager : IPartitionManager
 
             for (var i = 0; i < count; i++)
             {
-                var id = r.ReadInt32();
+                var id = r.ReadInt64();
                 var node = ClusterNode.Read(ref r);
 
                 primaryReplicas[id] = node;
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/Table.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/Table.cs
index 3bb5a7048b4..de4aba7e9f6 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/Table.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/Table.cs
@@ -117,7 +117,7 @@ namespace Apache.Ignite.Internal.Table
             KeyValueBinaryView = new KeyValueView<IIgniteTuple, IIgniteTuple>(
                 new RecordView<KvPair<IIgniteTuple, IIgniteTuple>>(this, 
pairSerializer, _sql));
 
-            PartitionManager = new PartitionManager(this);
+            PartitionDistribution = new PartitionManager(this);
         }
 
         /// <inheritdoc/>
@@ -133,7 +133,7 @@ namespace Apache.Ignite.Internal.Table
         public IKeyValueView<IIgniteTuple, IIgniteTuple> KeyValueBinaryView { 
get; }
 
         /// <inheritdoc/>
-        public IPartitionManager PartitionManager { get; }
+        public IPartitionDistribution PartitionDistribution { get; }
 
         /// <summary>
         /// Gets the associated socket.
diff --git a/modules/platforms/dotnet/Apache.Ignite/Table/IPartition.cs 
b/modules/platforms/dotnet/Apache.Ignite/Table/IPartition.cs
index 69c374c13de..0b2bae013d1 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Table/IPartition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Table/IPartition.cs
@@ -18,12 +18,14 @@
 namespace Apache.Ignite.Table;
 
 using System;
-using System.Diagnostics.CodeAnalysis;
 
 /// <summary>
 /// Table partition.
 /// </summary>
-[SuppressMessage("Design", "CA1040:Avoid empty interfaces", Justification = 
"Reviewed.")]
 public interface IPartition : IEquatable<IPartition>
 {
+    /// <summary>
+    /// Gets the identifier of the partition. The identifier is only 
guaranteed to be unique in the context of a table.
+    /// </summary>
+    long Id { get; }
 }
diff --git a/modules/platforms/dotnet/Apache.Ignite/Table/IPartitionManager.cs 
b/modules/platforms/dotnet/Apache.Ignite/Table/IPartitionDistribution.cs
similarity index 70%
copy from modules/platforms/dotnet/Apache.Ignite/Table/IPartitionManager.cs
copy to modules/platforms/dotnet/Apache.Ignite/Table/IPartitionDistribution.cs
index 536e482a52d..37487562c23 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Table/IPartitionManager.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Table/IPartitionDistribution.cs
@@ -25,22 +25,34 @@ using Mapper;
 using Network;
 
 /// <summary>
-/// Partition manager provides table partition information.
+/// Partition distribution provides table partition information.
+/// This interface can be used to get all partitions of a table, the location 
of the primary replica of a partition,
+/// the partition for a specific table key.
 /// </summary>
-public interface IPartitionManager
+public interface IPartitionDistribution
 {
     /// <summary>
     /// Gets the primary replicas for all partitions.
     /// <para />
     /// NOTE: Prefer <see cref="GetPrimaryReplicaAsync"/> for 
performance-critical code.
     /// </summary>
-    /// <returns>Map of partition to primary replica node.</returns>
+    /// <returns>Map of partition to the primary replica node.</returns>
     ValueTask<IReadOnlyDictionary<IPartition, IClusterNode>> 
GetPrimaryReplicasAsync();
 
+    /// <summary>
+    /// Gets all partitions hosted by the specified node as a primary replica 
as of the time of the call.
+    /// <para />
+    /// NOTE: This assignment may become outdated if a re-assignment happens 
on the cluster.
+    /// </summary>
+    /// <param name="node">Cluster node.</param>
+    /// <returns>A task representing the asynchronous operation with a list of 
all partitions hosted by the specified node
+    /// as a primary replica.</returns>
+    ValueTask<IReadOnlyList<IPartition>> GetPrimaryReplicasAsync(IClusterNode 
node);
+
     /// <summary>
     /// Gets the primary replica for the specified partition.
     /// <para />
-    /// NOTE: Prefer this method over <see cref="GetPrimaryReplicasAsync"/> 
for performance-critical code.
+    /// NOTE: Prefer this method over <see cref="GetPrimaryReplicasAsync()"/> 
for performance-critical code.
     /// </summary>
     /// <param name="partition">Partition.</param>
     /// <returns>Primary replica.</returns>
@@ -72,4 +84,10 @@ public interface IPartitionManager
     /// <typeparam name="TK">Key type.</typeparam>
     ValueTask<IPartition> GetPartitionAsync<TK>(TK key, IMapper<TK> mapper)
         where TK : notnull;
+
+    /// <summary>
+    /// Gets a list with all partitions.
+    /// </summary>
+    /// <returns>A task representing the asynchronous operation with a list of 
all partitions.</returns>
+    ValueTask<IReadOnlyList<IPartition>> GetPartitionsAsync();
 }
diff --git a/modules/platforms/dotnet/Apache.Ignite/Table/IPartitionManager.cs 
b/modules/platforms/dotnet/Apache.Ignite/Table/IPartitionManager.cs
index 536e482a52d..8a85b287a4a 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Table/IPartitionManager.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Table/IPartitionManager.cs
@@ -17,6 +17,7 @@
 
 namespace Apache.Ignite.Table;
 
+using System;
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.Threading.Tasks;
@@ -27,6 +28,7 @@ using Network;
 /// <summary>
 /// Partition manager provides table partition information.
 /// </summary>
+[Obsolete("Use IPartitionDistribution instead.")]
 public interface IPartitionManager
 {
     /// <summary>
@@ -34,13 +36,13 @@ public interface IPartitionManager
     /// <para />
     /// NOTE: Prefer <see cref="GetPrimaryReplicaAsync"/> for 
performance-critical code.
     /// </summary>
-    /// <returns>Map of partition to primary replica node.</returns>
+    /// <returns>Map of partition to the primary replica node.</returns>
     ValueTask<IReadOnlyDictionary<IPartition, IClusterNode>> 
GetPrimaryReplicasAsync();
 
     /// <summary>
     /// Gets the primary replica for the specified partition.
     /// <para />
-    /// NOTE: Prefer this method over <see cref="GetPrimaryReplicasAsync"/> 
for performance-critical code.
+    /// NOTE: Prefer this method over <see cref="GetPrimaryReplicasAsync()"/> 
for performance-critical code.
     /// </summary>
     /// <param name="partition">Partition.</param>
     /// <returns>Primary replica.</returns>
diff --git a/modules/platforms/dotnet/Apache.Ignite/Table/ITable.cs 
b/modules/platforms/dotnet/Apache.Ignite/Table/ITable.cs
index 91bea00f949..99b76cc3b5a 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Table/ITable.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Table/ITable.cs
@@ -17,6 +17,7 @@
 
 namespace Apache.Ignite.Table
 {
+    using System;
     using System.Collections.Generic;
     using System.Diagnostics.CodeAnalysis;
     using Internal.Table.Serialization;
@@ -50,7 +51,13 @@ namespace Apache.Ignite.Table
         /// <summary>
         /// Gets the partition manager.
         /// </summary>
-        public IPartitionManager PartitionManager { get; }
+        [Obsolete("Replaced by PartitionDistribution property.")]
+        public IPartitionManager PartitionManager => 
(IPartitionManager)PartitionDistribution;
+
+        /// <summary>
+        /// Gets the partition distribution.
+        /// </summary>
+        public IPartitionDistribution PartitionDistribution { get; }
 
         /// <summary>
         /// Gets the record view mapped to specified type <typeparamref 
name="T"/>.

Reply via email to