You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ha...@apache.org on 2023/05/24 14:19:12 UTC

[iotdb-client-csharp] 03/06: Initial Commit

This is an automated email from the ASF dual-hosted git repository.

haonan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iotdb-client-csharp.git

commit e05e72388af596fdb74d5e8c16228b28578ff56a
Author: lausannel <51...@qq.com>
AuthorDate: Wed May 24 21:34:55 2023 +0800

    Initial Commit
---
 .dockerignore                                      |    25 +
 .github/workflows/dotnet.yml                       |    25 +
 .github/workflows/e2e.yml                          |    28 +
 .gitignore                                         |    72 +
 .../Apache-IoTDB-Client-CSharp-UserCase.csproj     |    14 +
 Apache-IoTDB-Client-CSharp-UserCase/Program.cs     |   102 +
 Apache-IoTDB-Client-CSharp-UserCase/README.md      |    16 +
 Apache.IoTDB.sln                                   |   129 +
 LICENSE                                            |   236 +
 PUBLISH.md                                         |    89 +
 README.md                                          |    77 +
 README_ZH.md                                       |    74 +
 courgette.log                                      |     0
 docker-compose.dcproj                              |    15 +
 docker-compose.override.yml                        |     1 +
 docker-compose.yml                                 |    61 +
 docs/API.md                                        |    98 +
 ...67\347\253\257\344\273\213\347\273\215 (6).pdf" |   Bin 0 -> 207330 bytes
 ...216\237\347\224\237\346\216\245\345\217\243.md" |   103 +
 docs/assets/1.png                                  |   Bin 0 -> 122844 bytes
 docs/assets/2.png                                  |   Bin 0 -> 120090 bytes
 docs/assets/3.png                                  |   Bin 0 -> 117406 bytes
 docs/bytebuffer_zh.md                              |    59 +
 docs/session_pool_zh.md                            |   133 +
 docs/time_profile_zh.pdf                           |   Bin 0 -> 262072 bytes
 launchSettings.json                                |    14 +
 .../Apache.IoTDB.Samples.csproj                    |    29 +
 samples/Apache.IoTDB.Samples/Dockerfile            |    22 +
 samples/Apache.IoTDB.Samples/Program.cs            |    25 +
 .../Properties/launchSettings.json                 |    10 +
 .../SessionPoolTest.AlignedRecord.cs               |   480 +
 .../SessionPoolTest.AlignedTablet.cs               |   176 +
 .../Apache.IoTDB.Samples/SessionPoolTest.Record.cs |   553 +
 .../Apache.IoTDB.Samples/SessionPoolTest.Tablet.cs |   214 +
 .../SessionPoolTest.Template.cs                    |    85 +
 .../SessionPoolTest.TestNetwork.cs                 |   335 +
 .../SessionPoolTest.TimeSeries.cs                  |   178 +
 samples/Apache.IoTDB.Samples/SessionPoolTest.cs    |   500 +
 src/Apache.IoTDB.Data/Apache.IoTDB.Data.csproj     |    29 +
 src/Apache.IoTDB.Data/DataReaderExtensions.cs      |    85 +
 src/Apache.IoTDB.Data/IoTDBCommand.cs              |   547 +
 src/Apache.IoTDB.Data/IoTDBConnection.cs           |   353 +
 .../IoTDBConnectionStringBuilder.cs                |   408 +
 src/Apache.IoTDB.Data/IoTDBDataReader.cs           |   548 +
 src/Apache.IoTDB.Data/IoTDBException.cs            |    67 +
 src/Apache.IoTDB.Data/IoTDBFactory.cs              |    47 +
 src/Apache.IoTDB.Data/IoTDBParameter.cs            |   207 +
 src/Apache.IoTDB.Data/IoTDBParameterCollection.cs  |   351 +
 src/Apache.IoTDB.Data/IoTDBResult.cs               |    16 +
 src/Apache.IoTDB.Data/IoTDBTransaction.cs          |   108 +
 src/Apache.IoTDB.Data/Properties/AssemblyInfo.cs   |     5 +
 src/Apache.IoTDB/Apache.IoTDB.csproj               |    22 +
 src/Apache.IoTDB/Client.cs                         |    20 +
 src/Apache.IoTDB/ConcurrentClientQueue.cs          |    75 +
 src/Apache.IoTDB/DataStructure/ArrayExtensions.cs  |    76 +
 src/Apache.IoTDB/DataStructure/BitMap.cs           |   130 +
 src/Apache.IoTDB/DataStructure/ByteBuffer.cs       |   218 +
 src/Apache.IoTDB/DataStructure/GetSubArray.cs      |    47 +
 src/Apache.IoTDB/DataStructure/RowRecord.cs        |   212 +
 src/Apache.IoTDB/DataStructure/SessionDataSet.cs   |   340 +
 src/Apache.IoTDB/DataStructure/Tablet.cs           |   352 +
 src/Apache.IoTDB/IoTDBConstants.cs                 |    71 +
 .../Rpc/Generated/IClientRPCService.cs             | 19979 +++++++++++++++++++
 src/Apache.IoTDB/Rpc/Generated/ServerProperties.cs |   660 +
 .../Rpc/Generated/TConfigNodeLocation.cs           |   235 +
 .../Rpc/Generated/TConsensusGroupId.cs             |   183 +
 .../Rpc/Generated/TConsensusGroupType.cs           |    16 +
 .../Rpc/Generated/TDataNodeConfiguration.cs        |   205 +
 .../Rpc/Generated/TDataNodeLocation.cs             |   364 +
 src/Apache.IoTDB/Rpc/Generated/TEndPoint.cs        |   191 +
 src/Apache.IoTDB/Rpc/Generated/TFile.cs            |   203 +
 src/Apache.IoTDB/Rpc/Generated/TFilesResp.cs       |   222 +
 src/Apache.IoTDB/Rpc/Generated/TFlushReq.cs        |   239 +
 src/Apache.IoTDB/Rpc/Generated/TNodeResource.cs    |   179 +
 .../Rpc/Generated/TRegionMigrateFailedType.cs      |    18 +
 .../Rpc/Generated/TRegionReplicaSet.cs             |   222 +
 .../Rpc/Generated/TSAppendSchemaTemplateReq.cs     |   457 +
 .../Rpc/Generated/TSBackupConfigurationResp.cs     |   315 +
 .../Rpc/Generated/TSCancelOperationReq.cs          |   179 +
 .../Rpc/Generated/TSCloseOperationReq.cs           |   253 +
 .../Rpc/Generated/TSCloseSessionReq.cs             |   149 +
 src/Apache.IoTDB/Rpc/Generated/TSConnectionInfo.cs |   267 +
 .../Rpc/Generated/TSConnectionInfoResp.cs          |   179 +
 src/Apache.IoTDB/Rpc/Generated/TSConnectionType.cs |    16 +
 .../Rpc/Generated/TSCreateAlignedTimeseriesReq.cs  |   671 +
 .../Rpc/Generated/TSCreateMultiTimeseriesReq.cs    |   715 +
 .../Rpc/Generated/TSCreateSchemaTemplateReq.cs     |   233 +
 .../Rpc/Generated/TSCreateTimeseriesReq.cs         |   543 +
 src/Apache.IoTDB/Rpc/Generated/TSDeleteDataReq.cs  |   268 +
 .../Rpc/Generated/TSDropSchemaTemplateReq.cs       |   191 +
 .../Rpc/Generated/TSExecuteBatchStatementReq.cs    |   208 +
 .../Rpc/Generated/TSExecuteStatementReq.cs         |   423 +
 .../Rpc/Generated/TSExecuteStatementResp.cs        |   913 +
 .../Rpc/Generated/TSFetchMetadataReq.cs            |   246 +
 .../Rpc/Generated/TSFetchMetadataResp.cs           |   332 +
 .../Rpc/Generated/TSFetchResultsReq.cs             |   336 +
 .../Rpc/Generated/TSFetchResultsResp.cs            |   443 +
 .../Rpc/Generated/TSGetOperationStatusReq.cs       |   179 +
 .../Rpc/Generated/TSGetTimeZoneResp.cs             |   204 +
 .../Rpc/Generated/TSInsertRecordReq.cs             |   377 +
 .../Rpc/Generated/TSInsertRecordsOfOneDeviceReq.cs |   440 +
 .../Rpc/Generated/TSInsertRecordsReq.cs            |   457 +
 .../Rpc/Generated/TSInsertStringRecordReq.cs       |   443 +
 .../TSInsertStringRecordsOfOneDeviceReq.cs         |   457 +
 .../Rpc/Generated/TSInsertStringRecordsReq.cs      |   474 +
 .../Rpc/Generated/TSInsertTabletReq.cs             |   478 +
 .../Rpc/Generated/TSInsertTabletsReq.cs            |   592 +
 .../Rpc/Generated/TSLastDataQueryReq.cs            |   470 +
 src/Apache.IoTDB/Rpc/Generated/TSOpenSessionReq.cs |   362 +
 .../Rpc/Generated/TSOpenSessionResp.cs             |   321 +
 .../Rpc/Generated/TSProtocolVersion.cs             |    16 +
 .../Rpc/Generated/TSPruneSchemaTemplateReq.cs      |   233 +
 src/Apache.IoTDB/Rpc/Generated/TSQueryDataSet.cs   |   279 +
 .../Rpc/Generated/TSQueryNonAlignDataSet.cs        |   237 +
 .../Rpc/Generated/TSQueryTemplateReq.cs            |   276 +
 .../Rpc/Generated/TSQueryTemplateResp.cs           |   362 +
 .../Rpc/Generated/TSRawDataQueryReq.cs             |   500 +
 .../Rpc/Generated/TSSetSchemaTemplateReq.cs        |   233 +
 src/Apache.IoTDB/Rpc/Generated/TSSetTimeZoneReq.cs |   191 +
 src/Apache.IoTDB/Rpc/Generated/TSStatus.cs         |   321 +
 src/Apache.IoTDB/Rpc/Generated/TSTracingInfo.cs    |   684 +
 .../Rpc/Generated/TSUnsetSchemaTemplateReq.cs      |   233 +
 src/Apache.IoTDB/Rpc/Generated/TSchemaNode.cs      |   191 +
 .../Rpc/Generated/TSeriesPartitionSlot.cs          |   149 +
 src/Apache.IoTDB/Rpc/Generated/TSetTTLReq.cs       |   208 +
 .../Rpc/Generated/TSyncIdentityInfo.cs             |   275 +
 .../Rpc/Generated/TSyncTransportMetaInfo.cs        |   191 +
 .../Rpc/Generated/TTimePartitionSlot.cs            |   149 +
 .../Rpc/Generated/client.Extensions.cs             |   349 +
 .../Rpc/Generated/common.Extensions.cs             |   133 +
 src/Apache.IoTDB/SessionPool.cs                    |  2491 +++
 src/Apache.IoTDB/Template/InternalNode.cs          |    42 +
 src/Apache.IoTDB/Template/MeasurementNode.cs       |    57 +
 src/Apache.IoTDB/Template/Template.cs              |   125 +
 src/Apache.IoTDB/Template/TemplateNode.cs          |    41 +
 src/Apache.IoTDB/Utils.cs                          |    41 +
 .../Apache.IoTDB.Integration.Tests.csproj          |    19 +
 tests/Apache.IoTDB.Integration.Tests/Tests.cs      |    18 +
 tests/Apache.IoTDB.Tests/Apache.IoTDB.Tests.csproj |    19 +
 tests/Apache.IoTDB.Tests/Tests.cs                  |    18 +
 140 files changed, 51900 insertions(+)

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..bdca33b
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,25 @@
+**/.classpath
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/azds.yaml
+**/bin
+**/charts
+**/docker-compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+LICENSE
+README.md
\ No newline at end of file
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
new file mode 100644
index 0000000..5797b16
--- /dev/null
+++ b/.github/workflows/dotnet.yml
@@ -0,0 +1,25 @@
+name: .NET
+
+on:
+  push:
+    branches: [ main, dev/* ]
+  pull_request:
+    branches: [ main ]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Setup .NET
+      uses: actions/setup-dotnet@v1
+      with:
+        dotnet-version: 6.0.x
+    - name: Restore dependencies
+      run: dotnet restore "src/Apache.IoTDB/Apache.IoTDB.csproj"
+    - name: Build
+      run: dotnet build --no-restore "src/Apache.IoTDB/Apache.IoTDB.csproj"
+    - name: Test
+      run: dotnet test --no-build --verbosity normal "tests/Apache.IoTDB.Tests/Apache.IoTDB.Tests.csproj"
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
new file mode 100644
index 0000000..d539f3b
--- /dev/null
+++ b/.github/workflows/e2e.yml
@@ -0,0 +1,28 @@
+name: E2E Tests
+
+on:
+  push:
+    branches: [ main, dev/* ]
+  pull_request:
+    branches: [ main ]
+
+jobs:
+
+  build:
+    name: e2e test
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [ubuntu-latest]
+    steps:
+
+    - name: Check out code into the CSharp module directory
+      uses: actions/checkout@v2
+
+    - name: Set Docker & Run Test
+      run: |
+        docker network create --subnet 172.18.0.0/24 iotdb-network && docker-compose -f docker-compose.yml up --build --abort-on-container-exit --remove-orphans
+        
+    - name: Clean IoTDB & Shut Down Docker
+      run: |
+        docker-compose -f docker-compose.yml down
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3a7b0db
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,72 @@
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+**/tmp
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# DotCover is a Code Coverage Tool
+*.dotCove
+
+# Click-Once directory
+publish/
+
+### VisualStudioCode ###
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+
+### Rider ###
+.idea
+/.vs/Apache.IoTDB/FileContentIndex
+/.vs/ProjectEvaluation
+/.vs/Apache.IoTDB
diff --git a/Apache-IoTDB-Client-CSharp-UserCase/Apache-IoTDB-Client-CSharp-UserCase.csproj b/Apache-IoTDB-Client-CSharp-UserCase/Apache-IoTDB-Client-CSharp-UserCase.csproj
new file mode 100644
index 0000000..532250b
--- /dev/null
+++ b/Apache-IoTDB-Client-CSharp-UserCase/Apache-IoTDB-Client-CSharp-UserCase.csproj
@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net7.0</TargetFramework>
+    <RootNamespace>Apache_IoTDB_Client_CSharp_UserCase</RootNamespace>
+    <LangVersion>latest</LangVersion>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Apache.IoTDB" Version="1.0.0.3" />
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/Apache-IoTDB-Client-CSharp-UserCase/Program.cs b/Apache-IoTDB-Client-CSharp-UserCase/Program.cs
new file mode 100644
index 0000000..107931a
--- /dev/null
+++ b/Apache-IoTDB-Client-CSharp-UserCase/Program.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Apache.IoTDB;
+using Apache.IoTDB.DataStructure;
+
+namespace Apache.IoTDB.UserCase
+{
+    class Program
+    {
+        static string host = "localhost";
+        static int port = 6667;
+        static int pool_size = 2;
+
+
+        static async Task OpenAndCloseSessionPool()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (session_pool.IsOpen())
+            {
+                Console.WriteLine("SessionPool open success");
+            }
+            else
+            {
+                Console.WriteLine("SessionPool open failed");
+            }
+            await session_pool.Close();
+        }
+
+        static async Task CreateTimeseries()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+
+            await session_pool.DeleteStorageGroupAsync("root.ln.wf01.wt01");
+            var status = await session_pool.CreateTimeSeries("root.ln.wf01.wt01.status", TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.SNAPPY);
+            status = await session_pool.CreateTimeSeries("root.ln.wf01.wt01.temperature", TSDataType.DOUBLE, TSEncoding.PLAIN, Compressor.SNAPPY);
+            status = await session_pool.CreateTimeSeries("root.ln.wf01.wt01.hardware", TSDataType.TEXT, TSEncoding.PLAIN, Compressor.SNAPPY);
+
+            await session_pool.Close();
+        }
+
+        static async Task InsertRecord()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            long timestamp = 1;
+            var values = new List<object> { true, (double)1.1, "test" };
+            var measures = new List<string> { "status", "temperature", "hardware" };
+            var rowRecord = new RowRecord(timestamp, values, measures);
+            var status = await session_pool.InsertRecordAsync("root.ln.wf01.wt01", rowRecord);
+
+            await session_pool.Close();
+        }
+
+        static async Task InsertTablet()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            var device_id = "root.ln.wf01.wt01";
+            var measurement_lst = new List<string> { "status", "temperature", "hardware" };
+            var value_lst = new List<List<object>>
+            {
+                new() {true, (double)1.1, "test"},
+                new() {false, (double)2.2, "test2"},
+                new() {true, (double)3.3, "test3"}
+            };
+            var timestamp_lst = new List<long> { 1, 2, 3 };
+            var datatype_lst = new List<TSDataType> { TSDataType.BOOLEAN, TSDataType.DOUBLE, TSDataType.TEXT };
+            var tablet = new Tablet(device_id, measurement_lst, datatype_lst, value_lst, timestamp_lst);
+            var status = await session_pool.InsertTabletAsync(tablet);
+            await session_pool.Close();
+        }
+
+        static async Task ExecuteQueryStatement()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            var res = await session_pool.ExecuteQueryStatementAsync("select * from root.ln.wf01.wt01");
+            res.ShowTableNames();
+            while (res.HasNext())
+            {
+                Console.WriteLine(res.Next());
+            }
+            await res.Close();
+            await session_pool.Close();
+        }
+
+        static async Task Main(string[] args)
+        {
+            await OpenAndCloseSessionPool();
+            await CreateTimeseries();
+            await InsertRecord();
+            await InsertTablet();
+            await ExecuteQueryStatement();
+        }
+    }
+
+}
+
diff --git a/Apache-IoTDB-Client-CSharp-UserCase/README.md b/Apache-IoTDB-Client-CSharp-UserCase/README.md
new file mode 100644
index 0000000..3799d3d
--- /dev/null
+++ b/Apache-IoTDB-Client-CSharp-UserCase/README.md
@@ -0,0 +1,16 @@
+# Apache-IoTDB-Client-CSharp-UseCase
+Use case for csharp client of Apache IoTDB
+
+
+# Run this use case
+
+After cloning this project, you need to install Apache.IoTDB first.
+
+```shell
+dotnet add package Apache.IoTDB
+```
+
+Then you can run this project to test.
+```shell
+dotnet run
+``` 
diff --git a/Apache.IoTDB.sln b/Apache.IoTDB.sln
new file mode 100644
index 0000000..15d47ba
--- /dev/null
+++ b/Apache.IoTDB.sln
@@ -0,0 +1,129 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.2.32616.157
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AE9EFF1C-CB25-4089-B764-D834AC132501}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{11051AD6-88B3-44B4-A066-C59ED2E35AFD}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{AF185F16-80A9-49A8-98B4-B761FD197FF7}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Apache.IoTDB", "src\Apache.IoTDB\Apache.IoTDB.csproj", "{60FE924D-19EC-41A9-A114-70DD21A30545}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Apache.IoTDB.Samples", "samples\Apache.IoTDB.Samples\Apache.IoTDB.Samples.csproj", "{5B88D865-EFFD-4A13-8489-2172777859F5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Apache.IoTDB.Tests", "tests\Apache.IoTDB.Tests\Apache.IoTDB.Tests.csproj", "{414B31CD-57EB-478B-B734-542644CE48B0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Apache.IoTDB.Integration.Tests", "tests\Apache.IoTDB.Integration.Tests\Apache.IoTDB.Integration.Tests.csproj", "{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{DEAC57D3-4B3A-4650-85E3-5A179CD1DBAD}"
+	ProjectSection(SolutionItems) = preProject
+		docs\bytebuffer_zh.md = docs\bytebuffer_zh.md
+		PUBLISH.md = PUBLISH.md
+		README.md = README.md
+		README_ZH.md = README_ZH.md
+		docs\time_profile_zh.pdf = docs\time_profile_zh.pdf
+	EndProjectSection
+EndProject
+Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{4D457769-80CB-401F-9155-C3125C04FACD}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Apache.IoTDB.Data", "src\Apache.IoTDB.Data\Apache.IoTDB.Data.csproj", "{4308656F-D174-49A6-ACE4-15894B017D55}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Debug|x64.Build.0 = Debug|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Debug|x86.Build.0 = Debug|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Release|Any CPU.Build.0 = Release|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Release|x64.ActiveCfg = Release|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Release|x64.Build.0 = Release|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Release|x86.ActiveCfg = Release|Any CPU
+		{60FE924D-19EC-41A9-A114-70DD21A30545}.Release|x86.Build.0 = Release|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Debug|x64.Build.0 = Debug|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Debug|x86.Build.0 = Debug|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Release|x64.ActiveCfg = Release|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Release|x64.Build.0 = Release|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Release|x86.ActiveCfg = Release|Any CPU
+		{5B88D865-EFFD-4A13-8489-2172777859F5}.Release|x86.Build.0 = Release|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Debug|x64.Build.0 = Debug|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Debug|x86.Build.0 = Debug|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Release|x64.ActiveCfg = Release|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Release|x64.Build.0 = Release|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Release|x86.ActiveCfg = Release|Any CPU
+		{414B31CD-57EB-478B-B734-542644CE48B0}.Release|x86.Build.0 = Release|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Debug|x64.Build.0 = Debug|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Debug|x86.Build.0 = Debug|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Release|Any CPU.Build.0 = Release|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Release|x64.ActiveCfg = Release|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Release|x64.Build.0 = Release|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Release|x86.ActiveCfg = Release|Any CPU
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB}.Release|x86.Build.0 = Release|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Debug|x64.Build.0 = Debug|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Debug|x86.Build.0 = Debug|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Release|x64.ActiveCfg = Release|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Release|x64.Build.0 = Release|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Release|x86.ActiveCfg = Release|Any CPU
+		{4D457769-80CB-401F-9155-C3125C04FACD}.Release|x86.Build.0 = Release|Any CPU
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Debug|x64.ActiveCfg = Debug|x64
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Debug|x64.Build.0 = Debug|x64
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Debug|x86.ActiveCfg = Debug|x86
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Debug|x86.Build.0 = Debug|x86
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Release|x64.ActiveCfg = Release|x64
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Release|x64.Build.0 = Release|x64
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Release|x86.ActiveCfg = Release|x86
+		{4308656F-D174-49A6-ACE4-15894B017D55}.Release|x86.Build.0 = Release|x86
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{60FE924D-19EC-41A9-A114-70DD21A30545} = {AE9EFF1C-CB25-4089-B764-D834AC132501}
+		{5B88D865-EFFD-4A13-8489-2172777859F5} = {AF185F16-80A9-49A8-98B4-B761FD197FF7}
+		{414B31CD-57EB-478B-B734-542644CE48B0} = {11051AD6-88B3-44B4-A066-C59ED2E35AFD}
+		{133ECF70-6B6B-492B-A2A4-AA759CEE54BB} = {11051AD6-88B3-44B4-A066-C59ED2E35AFD}
+		{4308656F-D174-49A6-ACE4-15894B017D55} = {AE9EFF1C-CB25-4089-B764-D834AC132501}
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {F1C2DE69-7374-4521-9D86-500AA2517D4E}
+	EndGlobalSection
+EndGlobal
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b07d2b3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,236 @@
+Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+--------------------------------------------------------------------------------
+                           APACHE IOTDB SUBCOMPONENTS
+--------------------------------------------------------------------------------
+
+The following class is copied from maven-wrapper (https://github.com/takari/maven-wrapper),
+which is under Apache License 2.0:
+
+./.mvn/wrapper/MavenWrapperDownloader.java
+
+--------------------------------------------------------------------------------
+
+The following class is modified from Apache commons-collections
+
+./tsfile/src/main/java/org/apache/iotdb/tsfile/utils/Murmur128Hash.java
+Relevant pr is: https://github.com/apache/commons-collections/pull/83/
+
+--------------------------------------------------------------------------------
+
+The following files include code modified from Michael Burman's gorilla-tsc project.
+
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/encoder/GorillaEncoderV2.java
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/encoder/IntGorillaEncoder.java
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/encoder/LongGorillaEncoder.java
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/encoder/SinglePrecisionEncoderV2.java
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/encoder/DoublePrecisionEncoderV2.java
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/decoder/GorillaDecoderV2.java
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/decoder/IntGorillaDecoder.java
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/decoder/LongGorillaDecoder.java
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/decoder/SinglePrecisionDecoderV2.java
+./tsfile/src/main/java/org/apache/iotdb/tsfile/encoding/decoder/DoublePrecisionDecoderV2.java
+
+Copyright: 2016-2018 Michael Burman and/or other contributors
+Project page: https://github.com/burmanm/gorilla-tsc
+License: http://www.apache.org/licenses/LICENSE-2.0
\ No newline at end of file
diff --git a/PUBLISH.md b/PUBLISH.md
new file mode 100644
index 0000000..86013a3
--- /dev/null
+++ b/PUBLISH.md
@@ -0,0 +1,89 @@
+# Publish your own nuget package
+In this doc, we will introduce how to package and publish your own nuget package. Note that this will include the packaging and release of the two packages.
+
+## Package
+### Step 1: Rename
+Rename the following files/directories, where PACKAGE_NAME is the package name you expect. 
+
+Note that this name should be unique, otherwise it will be rejected. You can search at [nuget.org](https://www.nuget.org/) to confirm whether the name is unique.
+- `./src/Apache.IoTDB` => `./src/PACKAGE_NAME`
+- `./src/Apache.IoTDB/Apache.IoTDB.csproj` => `./src/PACKAGE_NAME/PACKAGE_NAME.csproj`
+- `./src/Apache.IoTDB.Rpc.Generated` => `./src/PACKAGE_NAME.Rpc.Generated`
+- `./src/Apache.IoTDB.Rpc.Generated/Apache.IoTDB.Rpc.Generated.csproj` => `./src/PACKAGE_NAME.Rpc.Generated/PACKAGE_NAME.Rpc.Generated.csproj`
+
+Besides, you also need to modify the configuration in `./src/Apache.IoTDB/Apache.IoTDB.csproj` to ensure that the project references are correct.
+``` xml
+<ProjectReference Include="..\Apache.IoTDB.Rpc.Generated\Apache.IoTDB.Rpc.Generated.csproj" />
+```
+to
+``` xml
+<ProjectReference Include="..\PACKAGE_NAME.Rpc.Generated\PACKAGE_NAME.Rpc.Generated.csproj" />
+```
+
+### Step 2: Add package information
+Modify `PACKAGE_NAME.csproj` to add package information, including version number, author, company, package description information, etc.
+
+ The commonly used ones are as follows, you can find a complete list in [NuGet pack and restore as MSBuild targets](https://docs.microsoft.com/en-us/nuget/reference/msbuild-targets#pack-target).
+
+- `Version`, a specific version number in the form Major.Minor.Patch\[-Suffix\] where -Suffix identifies [pre-release versions](https://docs.microsoft.com/en-us/nuget/create-packages/prerelease-packages). If not specified, the default value is 1.0.0.
+- `Authors`, author and owner information. If not specified, the default value is AssemblyName.
+- `Company`, your company name. If not specified, the default value is AssemblyName.
+- `PackageDescription`, A long description of the package for UI display.
+
+``` xml
+<PropertyGroup>
+  <Version>0.12.4</Version>
+  <Authors>Alice, Bob, Carol</Authors>
+  <Company>Test Inc.</Company>
+  <PackageDescription>A test nuget package.</PackageDescription>
+</PropertyGroup>
+```
+
+### Step 3: Build package with dotnet pack
+Execute the following commands in the same directory of `PACKAGE_NAME.csproj` and `PACKAGE_NAME.Rpc.Generated.csproj` to pack. You can find the generated package file `PACKAGE_NAME.VERSION.nupkg` in `bin/`.
+
+#### Debug
+``` bash
+dotnet pack PACKAGE_NAME.csproj --configuration debug 
+```
+
+#### Release
+``` bash
+dotnet pack PACKAGE_NAME.csproj --configuration release 
+```
+
+## Publish
+### Web portal: use the Upload Package tab on nuget.org
+1. Select Upload on the top menu of nuget.org and browse to the package location.
+![](https://docs.microsoft.com/en-us/nuget/nuget-org/media/publish_uploadyourpackage.png)
+
+2. nuget.org tells you if the package name is available. If it isn't, change the package identifier in your project, rebuild, and try the upload again.
+
+3. If the package name is available, nuget.org opens a Verify section in which you can review the metadata from the package manifest. To change any of the metadata, edit your project (project file or `.nuspec` file), rebuild, recreate the package, and upload again.
+
+4. When all the information is ready, select the Submit button.
+
+### Command line
+#### Step 1: Sign in & Create API keys
+1. [Sign into your nuget.org](https://www.nuget.org/) account or create an account if you don't have one already.
+
+2. Select your user name (on the upper right), then select **API Keys**.
+
+3. Select **Create**, provide a name for your key, select **Select Scopes > Push**. Enter **\*** for **Glob pattern**, then select **Create**. (See below for more about scopes.)
+
+4. Once the key is created, select **Copy** to retrieve the access key you need in the CLI:
+![](https://docs.microsoft.com/en-us/nuget/quickstart/media/qs_create-02-apikey.png)
+
+5. **Important**: Save your key in a secure location because you cannot copy the key again later on. If you return to the API key page, you need to regenerate the key to copy it. You can also remove the API key if you no longer want to push packages via the CLI.
+
+#### Step 2: Publish with dotnet nuget push
+1. Change to the directory containing the `.nupkg` file (`bin/Debug/` or `bin/Release/`).
+2. Execute the following command, specifying your package name and replacing the key value with your API key:
+``` .NET CLI
+dotnet nuget push PACKAGE_NAME.VERSION.nupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json
+```
+
+## References
+[MS Docs: Create a NuGet package](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package-dotnet-cli)
+
+[MS Docs: Publishing packages](https://docs.microsoft.com/en-us/nuget/nuget-org/publish-a-package)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b134037
--- /dev/null
+++ b/README.md
@@ -0,0 +1,77 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+    
+        http://www.apache.org/licenses/LICENSE-2.0
+    
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+[English](./README.md) | [中文](./README_ZH.md)
+
+# Apache IoTDB Client for C#
+
+## Overview
+
+This is the C# client of Apache IoTDB.
+
+[Apache IoTDB](https://iotdb.apache.org) (Internet of Things Database) is a data management system for time series data, which can provide users specific services, such as, data collection, storage and analysis. Due to its light weight structure, high performance and usable features together with its seamless integration with the Hadoop and Spark ecology, IoTDB meets the requirements of massive dataset storage, high throughput data input, and complex data analysis in the industrial IoT field.
+
+Apache IoTDB website: https://iotdb.apache.org
+Apache IoTDB Github: https://github.com/apache/iotdb
+
+## Installation
+
+### Install from NuGet Package
+
+We have prepared Nuget Package for C# users. Users can directly install the client through .NET CLI. [The link of our NuGet Package is here](https://www.nuget.org/packages/Apache.IoTDB/). Run the following command in the command line to complete installation
+
+```sh
+dotnet add package Apache.IoTDB
+```
+
+Note that the `Apache.IoTDB` package only supports versions greater than `.net framework 4.6.1`.
+
+## Prerequisites
+
+    .NET SDK Version >= 5.0 
+    .NET Framework >= 4.6.1
+
+## How to Use the Client (Quick Start)
+
+Users can quickly get started by referring to the use cases under the Apache-IoTDB-Client-CSharp-UserCase directory. These use cases serve as a useful resource for getting familiar with the client's functionality and capabilities.
+
+For those who wish to delve deeper into the client's usage and explore more advanced features, the samples directory contains additional code samples. 
+
+## Developer environment requirements for iotdb-client-csharp
+
+```
+.NET SDK Version >= 5.0
+.NET Framework >= 4.6.1
+ApacheThrift >= 0.14.1
+NLog >= 4.7.9
+```
+
+### OS
+
+* Linux, Macos or other unix-like OS
+* Windows+bash(WSL, cygwin, Git Bash)
+
+### Command Line Tools
+
+* dotnet CLI
+* Thrift
+
+## Publish your own client on nuget.org
+You can find out how to publish from this [doc](./PUBLISH.md).
\ No newline at end of file
diff --git a/README_ZH.md b/README_ZH.md
new file mode 100644
index 0000000..7a8216e
--- /dev/null
+++ b/README_ZH.md
@@ -0,0 +1,74 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+    
+        http://www.apache.org/licenses/LICENSE-2.0
+    
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+[English](./README.md) | [中文](./README_ZH.md)
+
+# Apache IoTDB C#语言客户端
+
+## 概览
+
+本仓库是Apache IoTDB的C#语言客户端,与其他语言支持相同语义的用户接口。
+
+Apache IoTDB website: https://iotdb.apache.org
+
+Apache IoTDB Github: https://github.com/apache/iotdb
+
+## 如何安装
+### 从NuGet Package安装
+
+我们为CSharp用户准备了NuGet包,用户可直接通过.NET CLI进行客户端安装,[NuGet包链接如下](https://www.nuget.org/packages/Apache.IoTDB/),命令行中运行如下命令即可完成安装
+    
+```sh
+dotnet add package Apache.IoTDB
+```
+
+请注意,`Apache.IoTDB`这个包仅支持大于`.net framework 4.6.1`的版本。
+## 环境准备
+
+    .NET SDK Version >= 5.0
+    .NET Framework >= 4.6.1 
+
+## 如何使用 (快速上手)
+用户可以通过参考Apache-IoTDB-Client-CSharp-UserCase目录下的用例快速入门。这些用例提供了客户端的基本功能和用法的参考。
+
+对于希望深入了解客户端用法并探索更高级特性的用户,samples目录包含了额外的代码示例。
+
+
+## iotdb-client-csharp的开发者环境要求
+
+```
+.NET SDK Version >= 5.0
+.NET Framework >= 4.6.1
+ApacheThrift >= 0.14.1
+NLog >= 4.7.9
+```
+
+### 操作系统
+
+* Linux、Macos或其他类unix系统
+* Windows+bash(WSL、cygwin、Git Bash)
+
+### 命令行工具
+
+* dotnet CLI
+* Thrift
+
+## 在 nuget.org 上发布你自己的客户端
+你可以在这个[文档](./PUBLISH.md)中找到如何发布
\ No newline at end of file
diff --git a/courgette.log b/courgette.log
new file mode 100644
index 0000000..e69de29
diff --git a/docker-compose.dcproj b/docker-compose.dcproj
new file mode 100644
index 0000000..56652dd
--- /dev/null
+++ b/docker-compose.dcproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
+  <PropertyGroup Label="Globals">
+    <ProjectVersion>2.1</ProjectVersion>
+    <DockerTargetOS>Linux</DockerTargetOS>
+    <ProjectGuid>4d457769-80cb-401f-9155-c3125c04facd</ProjectGuid>
+  </PropertyGroup>
+  <ItemGroup>
+    <None Include="docker-compose.override.yml">
+      <DependentUpon>docker-compose.yml</DependentUpon>
+    </None>
+    <None Include="docker-compose.yml" />
+    <None Include=".dockerignore" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
new file mode 100644
index 0000000..af2c815
--- /dev/null
+++ b/docker-compose.override.yml
@@ -0,0 +1 @@
+version: '3.4'
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..786cf10
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,61 @@
+version: '3.4'
+
+services:
+  apache.iotdb.samples:
+    image: ${DOCKER_REGISTRY-}apacheiotdbsamples
+    depends_on:
+       iotdb:
+        condition: service_healthy
+    links:
+      - iotdb
+    build:
+      context: .
+      dockerfile: samples/Apache.IoTDB.Samples/Dockerfile
+    networks:
+        iotdb-network:
+          ipv4_address: 172.18.0.2
+      
+  iotdb:
+   image: apache/iotdb:1.0.0-datanode
+   restart: always
+   container_name: iotdb-dn-1
+   depends_on:
+      iotdb-confignode-1:
+        condition: service_healthy
+   healthcheck:
+      test: ["CMD", "ls", "/iotdb/data"]
+      interval: 3s
+      timeout: 5s
+      retries: 30
+      start_period: 30s
+   ports:
+         - 6667:6667
+   networks:
+        iotdb-network:
+          ipv4_address: 172.18.0.3
+   environment:
+         - dn_rpc_address=iotdb
+         - dn_internal_address=iotdb
+         - dn_target_config_node_list=iotdb-confignode-1:22277
+  
+  iotdb-confignode-1:
+   image: apache/iotdb:1.0.0-confignode
+   restart: always
+   container_name: iotdb-cn-1
+   healthcheck:
+      test: ["CMD", "ls", "/iotdb/data"]
+      interval: 3s
+      timeout: 5s
+      retries: 30
+      start_period: 30s
+   networks:
+        iotdb-network:
+          ipv4_address: 172.18.0.4
+   environment:
+         - cn_internal_address=iotdb-confignode-1
+         - cn_target_config_node_list=iotdb-confignode-1:22277
+
+
+networks: 
+    iotdb-network:
+        external: true
\ No newline at end of file
diff --git a/docs/API.md b/docs/API.md
new file mode 100644
index 0000000..ffd2b4d
--- /dev/null
+++ b/docs/API.md
@@ -0,0 +1,98 @@
+# **核心概念**
+
+### **Row Record**
+
+- 对**IoTDB**中的`record`数据进行封装和抽象。
+- 示例:
+
+| timestamp | status | temperature |
+| --------- | ------ | ----------- |
+| 1         | 0      | 20          |
+
+- 构造方法:
+
+```c#
+var rowRecord = 
+  new RowRecord(long timestamps, List<object> values, List<string> measurements);
+```
+
+### **Tablet**
+
+- 一种类似于表格的数据结构,包含一个设备的若干行非空数据块。
+- 示例:
+
+| time | status | temperature |
+| ---- | ------ | ----------- |
+| 1    | 0      | 20          |
+| 2    | 0      | 20          |
+| 3    | 3      | 21          |
+
+- 构造方法:
+
+```c#
+var tablet = 
+  Tablet(string deviceId,  List<string> measurements, List<List<object>> values, List<long> timestamps);
+```
+
+
+
+# **API**
+
+### **基础接口**
+
+| api name       | parameters                | notes                    | use example                   |
+| -------------- | ------------------------- | ------------------------ | ----------------------------- |
+| Open           | bool                      | open session             | session_pool.Open(false)      |
+| Close          | null                      | close session            | session_pool.Close()          |
+| IsOpen         | null                      | check if session is open | session_pool.IsOpen()         |
+| OpenDebugMode  | LoggingConfiguration=null | open debug mode          | session_pool.OpenDebugMode()  |
+| CloseDebugMode | null                      | close debug mode         | session_pool.CloseDebugMode() |
+| SetTimeZone    | string                    | set time zone            | session_pool.GetTimeZone()    |
+| GetTimeZone    | null                      | get time zone            | session_pool.GetTimeZone()    |
+
+### **Record相关接口**
+
+| api name                            | parameters                    | notes                               | use example                                                  |
+| ----------------------------------- | ----------------------------- | ----------------------------------- | ------------------------------------------------------------ |
+| InsertRecordAsync                   | string, RowRecord             | insert single record                | session_pool.InsertRecordAsync("root.97209_TEST_CSHARP_CLIENT_GROUP.TEST_CSHARP_CLIENT_DEVICE", new RowRecord(1, values, measures)); |
+| InsertRecordsAsync                  | List<string>, List<RowRecord> | insert records                      | session_pool.InsertRecordsAsync(device_id, rowRecords)       |
+| InsertRecordsOfOneDeviceAsync       | string, List<RowRecord>       | insert records of one device        | session_pool.InsertRecordsOfOneDeviceAsync(device_id, rowRecords) |
+| InsertRecordsOfOneDeviceSortedAsync | string, List<RowRecord>       | insert sorted records of one device | InsertRecordsOfOneDeviceSortedAsync(deviceId, sortedRowRecords); |
+| TestInsertRecordAsync               | string, RowRecord             | test insert record                  | session_pool.TestInsertRecordAsync("root.97209_TEST_CSHARP_CLIENT_GROUP.TEST_CSHARP_CLIENT_DEVICE", rowRecord) |
+| TestInsertRecordsAsync              | List<string>, List<RowRecord> | test insert record                  | session_pool.TestInsertRecordsAsync(device_id, rowRecords)   |
+
+### **Tablet相关接口**
+
+| api name               | parameters   | notes                | use example                                  |
+| ---------------------- | ------------ | -------------------- | -------------------------------------------- |
+| InsertTabletAsync      | Tablet       | insert single tablet | session_pool.InsertTabletAsync(tablet)       |
+| InsertTabletsAsync     | List<Tablet> | insert tablets       | session_pool.InsertTabletsAsync(tablets)     |
+| TestInsertTabletAsync  | Tablet       | test insert tablet   | session_pool.TestInsertTabletAsync(tablet)   |
+| TestInsertTabletsAsync | List<Tablet> | test insert tablets  | session_pool.TestInsertTabletsAsync(tablets) |
+
+- ### **SQL语句接口**
+
+| api name                      | parameters | notes                          | use example                                                  |
+| ----------------------------- | ---------- | ------------------------------ | ------------------------------------------------------------ |
+| ExecuteQueryStatementAsync    | string     | execute sql query statement    | session_pool.ExecuteQueryStatementAsync("select * from root.97209_TEST_CSHARP_CLIENT_GROUP.TEST_CSHARP_CLIENT_DEVICE where time<15"); |
+| ExecuteNonQueryStatementAsync | string     | execute sql nonquery statement | session_pool.ExecuteNonQueryStatementAsync( "create timeseries root.97209_TEST_CSHARP_CLIENT_GROUP.TEST_CSHARP_CLIENT_DEVICE.status with datatype=BOOLEAN,encoding=PLAIN") |
+
+- ### 数据表接口
+
+| api name                   | parameters                                                   | notes                       | use example                                                  |
+| -------------------------- | ------------------------------------------------------------ | --------------------------- | ------------------------------------------------------------ |
+| SetStorageGroup            | string                                                       | set storage group           | session_pool.SetStorageGroup("root.97209_TEST_CSHARP_CLIENT_GROUP_01") |
+| CreateTimeSeries           | string, TSDataType, TSEncoding, Compressor                   | create time series          | session_pool.InsertTabletsAsync(tablets)                     |
+| DeleteStorageGroupAsync    | string                                                       | delete single storage group | session_pool.DeleteStorageGroupAsync("root.97209_TEST_CSHARP_CLIENT_GROUP_01") |
+| DeleteStorageGroupsAsync   | List<string>                                                 | delete storage group        | session_pool.DeleteStorageGroupAsync("root.97209_TEST_CSHARP_CLIENT_GROUP") |
+| CreateMultiTimeSeriesAsync | List<string>, List<TSDataType> , List<TSEncoding> , List<Compressor> | create multi time series    | session_pool.CreateMultiTimeSeriesAsync(ts_path_lst, data_type_lst, encoding_lst, compressor_lst); |
+| DeleteTimeSeriesAsync      | List<string>                                                 | delete time series          |                                                              |
+| DeleteTimeSeriesAsync      | string                                                       | delete time series          |                                                              |
+| DeleteDataAsync            | List<string>, long, long                                     | delete data                 | session_pool.DeleteDataAsync(ts_path_lst, 2, 3)              |
+
+- ### **辅助接口**
+
+| api name                   | parameters | notes                       | use example                                          |
+| -------------------------- | ---------- | --------------------------- | ---------------------------------------------------- |
+| CheckTimeSeriesExistsAsync | string     | check if time series exists | session_pool.CheckTimeSeriesExistsAsync(time series) |
+
diff --git "a/docs/Apache IoTDB C#\345\256\242\346\210\267\347\253\257\344\273\213\347\273\215 (6).pdf" "b/docs/Apache IoTDB C#\345\256\242\346\210\267\347\253\257\344\273\213\347\273\215 (6).pdf"
new file mode 100644
index 0000000..ccf2b93
Binary files /dev/null and "b/docs/Apache IoTDB C#\345\256\242\346\210\267\347\253\257\344\273\213\347\273\215 (6).pdf" differ
diff --git "a/docs/C#\345\216\237\347\224\237\346\216\245\345\217\243.md" "b/docs/C#\345\216\237\347\224\237\346\216\245\345\217\243.md"
new file mode 100644
index 0000000..2588631
--- /dev/null
+++ "b/docs/C#\345\216\237\347\224\237\346\216\245\345\217\243.md"
@@ -0,0 +1,103 @@
+# C# 原生接口
+
+## 依赖
+
+- .NET SDK >= 5.0 或 .NET Framework 4.x
+- ApacheThrift >= 0.14.1
+- NLog >= 4.7.9
+
+## 安装
+
+您可以使用 NuGet Package Manager, .NET CLI等工具来安装,以 .NET CLI为例
+
+如果您使用的是.NET 5.0 或者更高版本的SDK,输入如下命令即可安装最新的NuGet包
+
+```
+dotnet add package Apache.IoTDB
+```
+
+为了适配 .NET Framework 4.x,我们单独构建了一个NuGet包,如果您使用的是.NET Framework 4.x,输入如下命令即可安装最新的包
+
+```bash
+dotnet add package Apache.IoTDB.framework
+```
+
+如果您想安装更早版本的客户端,只需要指定版本即可
+
+```bash
+# 安装0.12.1.2版本的客户端
+dotnet add package Apache.IoTDB --version 0.12.1.2
+```
+
+## 基本接口说明
+
+Session接口在语义上和其他语言客户端相同
+
+```c#
+// 参数定义
+string host = "localhost";
+int port = 6667;
+int pool_size = 2;
+
+// 初始化session
+var session_pool = new SessionPool(host, port, pool_size);
+
+// 开启session
+await session_pool.Open(false);
+
+// 创建时间序列
+await session_pool.CreateTimeSeries("root.test_group.test_device.ts1", TSDataType.TEXT, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+await session_pool.CreateTimeSeries("root.test_group.test_device.ts2", TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+await session_pool.CreateTimeSeries("root.test_group.test_device.ts3", TSDataType.INT32, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+
+// 插入record
+var measures = new List<string>{"ts1", "ts2", "ts3"};
+var values = new List<object> { "test_text", true, (int)123 };
+var timestamp = 1;
+var rowRecord = new RowRecord(timestamp, values, measures);
+await session_pool.InsertRecordAsync("root.test_group.test_device", rowRecord);
+
+// 插入Tablet
+var timestamp_lst = new List<long>{ timestamp + 1 };
+var value_lst = new List<object> {new() {"iotdb", true, (int) 12}};
+var tablet = new Tablet("root.test_group.test_device", measures, value_lst, timestamp_ls);
+await session_pool.InsertTabletAsync(tablet);
+
+// 关闭Session
+await session_pool.Close();
+```
+
+详细接口信息可以参考[接口文档](https://github.com/eedalong/Apache-IoTDB-Client-CSharp/blob/main/docs/API.md)
+
+用法可以参考[用户示例](https://github.com/eedalong/Apache-IoTDB-Client-CSharp/tree/main/samples/Apache.IoTDB.Samples)
+
+## 连接池
+
+为了实现并发客户端请求,我们提供了针对原生接口的连接池(`SessionPool`),由于`SessionPool`本身为`Session`的超集,当`SessionPool`的`pool_size`参数设置为1时,退化为原来的`Session`
+
+我们使用`ConcurrentQueue`数据结构封装了一个客户端队列,以维护与服务端的多个连接,当调用`Open()`接口时,会在该队列中创建指定个数的客户端,同时通过`System.Threading.Monitor`类实现对队列的同步访问。
+
+当请求发生时,会尝试从连接池中寻找一个空闲的客户端连接,如果没有空闲连接,那么程序将需要等待直到有空闲连接
+
+当一个连接被用完后,他会自动返回池中等待下次被使用
+
+在使用连接池后,客户端的并发性能提升明显,[这篇文档](https://github.com/eedalong/Apache-IoTDB-Client-CSharp/blob/main/docs/session_pool_zh.md#%E5%BB%BA%E7%AB%8Bclient%E8%BF%9E%E6%8E%A5)展示了使用线程池比起单线程所带来的性能提升
+
+## ByteBuffer
+
+在传入RPC接口参数时,需要对Record和Tablet两种数据结构进行序列化,我们主要通过封装的ByteBuffer类实现
+
+在封装字节序列的基础上,我们进行了内存预申请与内存倍增的优化,减少了序列化过程中内存的申请和释放,在一个拥有20000行的Tablet上进行序列化测试时,速度比起原生的数组动态增长具有**35倍的性能加速**
+
+详见以下两篇文档
+
+[ByteBuffer详细介绍](https://github.com/eedalong/Apache-IoTDB-Client-CSharp/blob/main/docs/bytebuffer_zh.md)
+
+[ByteBuffer性能测试文档](https://bnw3yl170k.feishu.cn/docs/doccnxiHV7avYiFBkuEljCLIYO4#mMS5HE)
+
+## 异常重连
+
+当服务端发生异常或者宕机重启时,客户端中原来通过`Open()`产生的的session会失效,抛出`TException`异常
+
+为了避免这一情况的发生,我们对大部分的接口进行了增强,一旦出现连接问题,就会尝试重新调用`Open()`接口并创建新的Session,并尝试重新发送对应的请求
+
diff --git a/docs/assets/1.png b/docs/assets/1.png
new file mode 100644
index 0000000..e1c446e
Binary files /dev/null and b/docs/assets/1.png differ
diff --git a/docs/assets/2.png b/docs/assets/2.png
new file mode 100644
index 0000000..20c2b09
Binary files /dev/null and b/docs/assets/2.png differ
diff --git a/docs/assets/3.png b/docs/assets/3.png
new file mode 100644
index 0000000..b2bce44
Binary files /dev/null and b/docs/assets/3.png differ
diff --git a/docs/bytebuffer_zh.md b/docs/bytebuffer_zh.md
new file mode 100644
index 0000000..a482789
--- /dev/null
+++ b/docs/bytebuffer_zh.md
@@ -0,0 +1,59 @@
+## IoTDB CSharp Client ByteBuffer实现介绍
+在进行`RowRecords`以及`Tablet`的插入时,我们需要对多行RowRecord和Tablet进行序列化以进行发送。客户端中的序列化实现主要依赖于ByteBuffer完成。接下来我们介绍ByteBuffer的实现细节。本文包含如下几点内容:
+ - 序列化的协议
+ - C#与Java的大小端的差异
+ - ByteBuffer内存倍增算法
+
+### 一、序列化协议
+客户端向IoTDB服务器发送的序列化数据总体应该包含两个信息。
+ -  数据类型
+ -  数据本身
+
+其中对于`字符串`的序列化时,我们需要再加入字符串的长度信息。即一个字符串的序列化完整结果为:
+
+    [类型][长度][数据内容]
+接下来我们分别介绍`RowRecord`、`Tablet`的序列化方式
+
+#### 1.1 RowRecord
+我们对RowRecord进行序列化时,`伪代码`如下:
+
+        public byte[] value_to_bytes(List<TSDataType> data_types, List<string> values){
+            ByteBuffer buffer = new ByteBuffer(values.Count);
+            for(int i = 0;i < data_types.Count(); i++){
+                buffer.add_type((data_types[i]);
+                buffer.add_val(values[i]);
+            }
+        }
+
+对于其序列化的结果格式如下:
+
+    [数据类型1][数据1][数据类型2][数据2]...[数据类型N][数据N]
+ 其中数据类型为自定义的`Enum`变量,分别如下:
+
+    public enum TSDataType{BOOLEAN, INT32, INT64, FLOAT, DOUBLE, TEXT, NONE};
+
+#### 1.2. Tablet序列化
+使用`Tabelt`进行数据插入时有如下限制:
+
+    限制:Tablet中数据不能有空值
+由于向 `IoTDB`服务器发送`Tablet`数据插入请求时会携带`行数`, `列数`, `列数据类型`,所以`Tabelt`序列化时我们不需要加入数据类型信息。`Tablet`是`按照列进行序列化`,这是因为后端可以通过行数得知出当前列的元素个数,同时根据列类型来对数据进行解析。
+
+## CSharp与Java序列化数据时的大小端差异
+由于Java序列化默认大端协议,而CSharp序列化默认得到小端序列。所以我们在CSharp中序列化数据之后,需要对数据进行反转这样后端才可以正常解析。同时当我们从后端获取到序列化的结果时(如`SessionDataset`),我们也需要对获得的数据进行反转以解析内容。这其中特例便是字符串的序列化,CSharp中对字符串的序列化结果为大端序,所以序列化字符串或者接收到字符串序列化结果时,不需要反转序列结果。
+
+## ByteBuffer内存倍增法
+拥有数万行的Tablet的序列化结果可能有上百兆,为了能够高效的实现大`Tablet`的序列化,我们对ByteBuffer使用`内存倍增法`的策略来减少序列化过程中对于内存的申请和释放。即当当前的buffer的长度不足以放下序列化结果时,我们将当前buffer的内存`至少`扩增2倍。这极大的减少了内存的申请释放次数,加速了大Tablet的序列化速度。
+
+    private void extend_buffer(int space_need){
+            if(write_pos + space_need >= total_length){
+                total_length = max(space_need, total_length);
+                byte[] new_buffer = new byte[total_length * 2];
+                buffer.CopyTo(new_buffer, 0);
+                buffer = new_buffer;
+                total_length = 2 * total_length;
+            }
+    }
+同时在序列化`Tablet`时,我们首先根据Tablet的`行数`,`列数`以及每一列的数据类型估计当前`Tablet`序列化结果所需要的内存大小,并在初始化时进行内存的申请。这进一步的减少了内存的申请释放频率。
+
+通过上述的策略,我们在一个有`20000`行的Tablet上进行测试时,序列化速度相比Naive数组长度动态生长实现算法具有约35倍的性能加速。
+
diff --git a/docs/session_pool_zh.md b/docs/session_pool_zh.md
new file mode 100644
index 0000000..53ea321
--- /dev/null
+++ b/docs/session_pool_zh.md
@@ -0,0 +1,133 @@
+# IoTDB-CSharp客户端的定制化SessionPool机制
+
+### 主要参数
+
+- `_username`:用户名
+- `_password`:密码
+- `_zoneId`:时区
+- `_host`:主机ip
+- `_port`:端口号
+- `_fetchSize`:单次请求数据大小
+- `_poolSize`:线程池大小(默认为4)
+
+### 数据结构
+
+- #### Client
+
+该数据结构对**客户端连接**进行了封装,维护一个客户端实例**TSIService.Client、**线程码**SessionId**与状态码**StatementId**以及分帧传输流**TFramedTransport。**
+
+```c#
+public Client(TSIService.Client client, long sessionId, long statementId, TFramedTransport transport)
+{
+    ServiceClient = client;
+    SessionId = sessionId;
+    StatementId = statementId;
+    Transport = transport;
+}
+```
+
+- #### ConcurrentClientQueue
+
+该数据结构封装了一个**高效的线程安全队列**,用于维护客户端与服务器的多个Client连接。
+
+### Client-Server交互全流程
+
+- #### 建立Client连接
+  - 用户创建一个**SessionPool**并调用**Open()**函数后,系统会创建一个**ConcurrentClientQueue**实例,并向其中创建并添加 _poolSize 个**Client**连接(客户端连接)。
+  - 创建**Client**连接时,首先建立Tcp连接并获得**TSIService.Client**的实例,然后通过**openSessionAsync()**函数为该客户端开启一个新的线程,开启成功后获得线程码**SessionId**与状态码**StatementId**,进而创建一个**Client**连接。
+  - 添加**Client**连接时,调用**ConcurrentClientQueue**的**Add()**函数,代码如下:
+
+```c#
+public void Add(Client client)
+{
+    Monitor.Enter(ClientQueue);
+    ClientQueue.Enqueue(client);
+    Monitor.Pulse(ClientQueue);
+    Monitor.Exit(ClientQueue);
+}
+```
+
+> 通过System.Threading.**Monitor**类实现多线程对**ConcurrentQueue**的同步访问,以确保数据的安全性。
+
+- #### 获取空闲连接
+
+当请求发生时,系统会在**ConcurrentClientQueue**中寻找一个空闲的**Client**连接,即调用 **ConcurrentClientQueue** 的**Take()**函数,代码如下:
+
+```c#
+public Client Take()
+{
+    Monitor.Enter(ClientQueue);
+    if (ClientQueue.IsEmpty)
+    {
+        Monitor.Wait(ClientQueue);
+    }
+    ClientQueue.TryDequeue(out var client);
+    Monitor.Exit(ClientQueue);
+    return client;
+}
+```
+
+如果请求时**ConcurrentClientQueue**中没有空闲**Client**连接时,系统会调用 Monitor 类中的 **Wait()** 方法让线程等待,直到队列不为空时,弹出空闲**Client**连接。
+
+- #### 执行操作
+
+获取到空闲Client连接后,系统便在此连接上进行数据操作,示例如下:
+
+```c#
+public async Task<int> InsertRecordAsync(string deviceId, RowRecord record)
+{
+    var client = _clients.Take();    // 获取空闲的Client连接
+    var req = new TSInsertRecordReq(client.SessionId, deviceId, record.Measurements, record.ToBytes(),
+        record.Timestamps);
+    try
+    {
+        var status = await client.ServiceClient.insertRecordAsync(req);
+        if (_debugMode)
+        {
+            _logger.Info("insert one record to device {0}, server message: {1}", deviceId, status.Message);
+        }
+        return _utilFunctions.verify_success(status, SuccessCode);
+    }
+
+    catch (TException e)
+    {
+        throw new TException("Record insertion failed", e);
+    }
+
+    finally
+    {
+        _clients.Add(client);
+    }
+}
+```
+
+- #### 回收Client连接
+
+当操作结束后,系统会回收该空闲连接,通过 **ConcurrentClientQueue.Add()** 函数将该连接重新加入队列,并在在添加后会通过 **Pulse()** 方法通知其他处于等待状态的线程。考虑到操作过程中可能出现异常,所有操作都被放在try-catch块中,即使捕获到了异常也会将该Client连接放回队列中,防止连接丢失。
+
+### 对比评测
+
+#### 本地测试
+
+> ##### 测试环境:
+>
+> - 操作系统:macOS
+> - 处理器:2.3GHz 八核 Intel Core i9
+> - IoTDB版本:0.12.0
+
+<img src="assets/1.png" alt="1" style="zoom:67%;" />
+
+#### 远端测试
+
+> ##### 测试环境:
+>
+> - 本地:
+>   - 操作系统:macOS
+>   - 处理器:2.3GHz 八核 Intel Core i9
+> - 服务器:
+>   - IoTDB版本:0.12.1
+
+<img src="assets/2.png" alt="2" style="zoom:67%;" />
+
+<img src="assets/3.png" alt="3" style="zoom:67%;" />
+
diff --git a/docs/time_profile_zh.pdf b/docs/time_profile_zh.pdf
new file mode 100644
index 0000000..a8ed50f
Binary files /dev/null and b/docs/time_profile_zh.pdf differ
diff --git a/launchSettings.json b/launchSettings.json
new file mode 100644
index 0000000..21ab158
--- /dev/null
+++ b/launchSettings.json
@@ -0,0 +1,14 @@
+{
+  "profiles": {
+    "Docker Compose": {
+      "commandName": "DockerCompose",
+      "commandVersion": "1.0",
+      "composeLaunchAction": "None",
+      "composeLaunchServiceName": "apache.iotdb.samples",
+      "serviceActions": {
+        "apache.iotdb.samples": "StartDebugging",
+        "iotdb": "StartWithoutDebugging"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/Apache.IoTDB.Samples.csproj b/samples/Apache.IoTDB.Samples/Apache.IoTDB.Samples.csproj
new file mode 100644
index 0000000..93f821e
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/Apache.IoTDB.Samples.csproj
@@ -0,0 +1,29 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <OutputType>Exe</OutputType>
+        <TargetFramework>net6.0</TargetFramework>
+        <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
+        <DockerfileContext>..\..</DockerfileContext>
+    </PropertyGroup>
+
+    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+      <LangVersion>default</LangVersion>
+    </PropertyGroup>
+
+    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+      <LangVersion>default</LangVersion>
+    </PropertyGroup>
+
+    <ItemGroup>
+      <PackageReference Include="ConsoleTableExt" Version="3.2.0" />
+      <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.15.1" />
+      <PackageReference Include="NLog.Extensions.Logging" Version="5.0.1" />
+    </ItemGroup>
+
+    <ItemGroup>
+      <ProjectReference Include="..\..\src\Apache.IoTDB.Data\Apache.IoTDB.Data.csproj" />
+      <ProjectReference Include="..\..\src\Apache.IoTDB\Apache.IoTDB.csproj" />
+    </ItemGroup>
+
+</Project>
diff --git a/samples/Apache.IoTDB.Samples/Dockerfile b/samples/Apache.IoTDB.Samples/Dockerfile
new file mode 100644
index 0000000..e9ecdf1
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/Dockerfile
@@ -0,0 +1,22 @@
+#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
+
+FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base
+WORKDIR /app
+
+FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
+WORKDIR /src
+COPY ["samples/Apache.IoTDB.Samples/Apache.IoTDB.Samples.csproj", "samples/Apache.IoTDB.Samples/"]
+COPY ["src/Apache.IoTDB/Apache.IoTDB.csproj", "src/Apache.IoTDB/"]
+COPY ["src/Apache.IoTDB.Data/Apache.IoTDB.Data.csproj", "src/Apache.IoTDB.Data/"]
+RUN dotnet restore "samples/Apache.IoTDB.Samples/Apache.IoTDB.Samples.csproj"
+COPY . .
+WORKDIR "/src/samples/Apache.IoTDB.Samples"
+RUN dotnet build "Apache.IoTDB.Samples.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "Apache.IoTDB.Samples.csproj" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "Apache.IoTDB.Samples.dll"]
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/Program.cs b/samples/Apache.IoTDB.Samples/Program.cs
new file mode 100644
index 0000000..2a431ef
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/Program.cs
@@ -0,0 +1,25 @@
+using Microsoft.Extensions.Logging;
+using NLog.Extensions.Logging;
+using System;
+using System.Threading.Tasks;
+
+namespace Apache.IoTDB.Samples
+{
+    public static class Program
+    {
+        public static async Task Main(string[] args)
+        {
+            var sessionPoolTest = new SessionPoolTest("iotdb");
+           await  sessionPoolTest.Test() ;
+        }
+
+        public static void OpenDebugMode(this SessionPool session)
+        {
+            session.OpenDebugMode(builder =>
+            {
+                builder.AddConsole();
+                builder.AddNLog();
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/Properties/launchSettings.json b/samples/Apache.IoTDB.Samples/Properties/launchSettings.json
new file mode 100644
index 0000000..7195264
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/Properties/launchSettings.json
@@ -0,0 +1,10 @@
+{
+  "profiles": {
+    "Apache.IoTDB.Samples": {
+      "commandName": "Project"
+    },
+    "Docker": {
+      "commandName": "Docker"
+    }
+  }
+}
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedRecord.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedRecord.cs
new file mode 100644
index 0000000..3d414a0
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedRecord.cs
@@ -0,0 +1,480 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Apache.IoTDB.DataStructure;
+namespace Apache.IoTDB.Samples
+{
+    public partial class SessionPoolTest
+    {
+        public async Task TestInsertAlignedRecord()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            int status;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            string prefixPath = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurements = new List<string> { test_measurements[1], test_measurements[2], test_measurements[3] };
+            var types = new List<TSDataType> { TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32 };
+            var encodings = new List<TSEncoding> { TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN };
+            var compressors = new List<Compressor> { Compressor.UNCOMPRESSED, Compressor.UNCOMPRESSED, Compressor.UNCOMPRESSED };
+            //status = await session_pool.CreateAlignedTimeseriesAsync(prefixPath, measurements, types, encodings, compressors);
+            //System.Diagnostics.Debug.Assert(status == 0);
+
+            var measures = new List<string>
+                { test_measurements[1], test_measurements[2], test_measurements[3] };
+            var values = new List<object> { "test_text", true, (int)123 };
+            var tasks = new List<Task<int>>();
+            var start_ms = DateTime.Now.Ticks / 10000;
+            for (var timestamp = 1; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                var rowRecord = new RowRecord(timestamp, values, measures);
+                var task = session_pool.InsertAlignedRecordAsync(
+                    string.Format("{0}.{1}", test_group_name, test_device), rowRecord);
+                tasks.Add(task);
+            }
+            Task.WaitAll(tasks.ToArray());
+            var end_ms = DateTime.Now.Ticks / 10000;
+            Console.WriteLine(string.Format("total insert record time is {0}", end_ms - start_ms));
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertAlignedRecordAsync Passed");
+        }
+        public async Task TestInsertAlignedStringRecord()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            status = await session_pool.CreateAlignedTimeseriesAsync(
+                string.Format("{0}.{1}", test_group_name, test_device),
+                new List<string>() { test_measurements[0], test_measurements[1], test_measurements[2] },
+                new List<TSDataType>() { TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT },
+                new List<TSEncoding>() { TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN },
+                new List<Compressor>() { Compressor.UNCOMPRESSED, Compressor.UNCOMPRESSED, Compressor.UNCOMPRESSED });
+
+            System.Diagnostics.Debug.Assert(status == 0);
+            var measurements = new List<string>
+                {test_measurements[0], test_measurements[1], test_measurements[2]};
+            var values = new List<string> { "test_text1", "test_text2", "test_text3" };
+            var tasks = new List<Task<int>>();
+            var start_ms = DateTime.Now.Ticks / 10000;
+            for (var timestamp = 1; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                var task = session_pool.InsertAlignedStringRecordAsync(
+                    string.Format("{0}.{1}", test_group_name, test_device), measurements, values, timestamp);
+                tasks.Add(task);
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            var end_ms = DateTime.Now.Ticks / 10000;
+            Console.WriteLine(string.Format("total insert aligned string record time is {0}", end_ms - start_ms));
+            var res = await session_pool.ExecuteQueryStatementAsync("select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            var res_cnt = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_cnt++;
+            }
+            Console.WriteLine(res_cnt + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_cnt == fetch_size * processed_size);
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertAlignedStringRecordAsync Passed");
+        }
+        public async Task TestInsertAlignedRecords()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            string prefixPath = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurement_lst = new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4],
+                test_measurements[5],
+                test_measurements[6]
+            };
+            var data_type_lst = new List<TSDataType>()
+            {
+                TSDataType.BOOLEAN, TSDataType.INT32, TSDataType.INT64, TSDataType.DOUBLE, TSDataType.FLOAT,
+                TSDataType.TEXT
+            };
+            var encoding_lst = new List<TSEncoding>()
+            {
+                TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN,
+                TSEncoding.PLAIN
+            };
+            var compressor_lst = new List<Compressor>()
+            {
+                Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY,
+                Compressor.SNAPPY
+            };
+            status = await session_pool.CreateAlignedTimeseriesAsync(prefixPath, measurement_lst, data_type_lst, encoding_lst,
+                compressor_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var device_id = new List<string>() { };
+            for (var i = 0; i < 3; i++) device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+            var measurements_lst = new List<List<string>>() { };
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4]
+            });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4],
+                test_measurements[5],
+                test_measurements[6]
+            });
+            var values_lst = new List<List<object>>() { };
+            values_lst.Add(new List<object>() { true, (int)123 });
+            values_lst.Add(new List<object>() { true, (int)123, (long)456, (double)1.1 });
+            values_lst.Add(new List<object>()
+                {true, (int) 123, (long) 456, (double) 1.1, (float) 10001.1, "test_record"});
+            var timestamp_lst = new List<long>() { 1, 2, 3 };
+            var rowRecords = new List<RowRecord>() { };
+            for (var i = 0; i < 3; i++)
+            {
+                var rowRecord = new RowRecord(timestamp_lst[i], values_lst[i], measurements_lst[i]);
+                rowRecords.Add(rowRecord);
+            }
+
+            status = await session_pool.InsertAlignedRecordsAsync(device_id, rowRecords);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            Console.WriteLine(status);
+
+            // large data test
+            device_id = new List<string>() { };
+            rowRecords = new List<RowRecord>() { };
+            var tasks = new List<Task<int>>();
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+                rowRecords.Add(new RowRecord(timestamp, new List<object>() { true, (int)123 },
+                    new List<string>() { test_measurements[1], test_measurements[2] }));
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertAlignedRecordsAsync(device_id, rowRecords));
+                    device_id = new List<string>() { };
+                    rowRecords = new List<RowRecord>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            res.ShowTableNames();
+            var record_count = fetch_size * processed_size;
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == record_count);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertAlignedRecords Passed!");
+        }
+        public async Task TestInsertAlignedStringRecords()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            string prefixPath = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurement_lst = new List<string>() { test_measurements[1], test_measurements[2] };
+            var data_type_lst = new List<TSDataType>() { TSDataType.TEXT, TSDataType.TEXT };
+            var encoding_lst = new List<TSEncoding>() { TSEncoding.PLAIN, TSEncoding.PLAIN };
+            var compressor_lst = new List<Compressor>() { Compressor.SNAPPY, Compressor.SNAPPY };
+            status = await session_pool.CreateAlignedTimeseriesAsync(prefixPath, measurement_lst, data_type_lst, encoding_lst,
+                compressor_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var device_id = new List<string>() { };
+            for (var i = 0; i < 3; i++) device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+            var measurements_lst = new List<List<string>>() { };
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            var values_lst = new List<List<string>>() { };
+            values_lst.Add(new List<string>() { "test1", "test2" });
+            values_lst.Add(new List<string>() { "test3", "test4" });
+            values_lst.Add(new List<string>() { "test5", "test6" });
+            List<long> timestamp_lst = new List<long>() { 1, 2, 3 };
+
+            status = await session_pool.InsertAlignedStringRecordsAsync(device_id, measurements_lst, values_lst, timestamp_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+
+            // large data test
+            device_id = new List<string>() { };
+            measurements_lst = new List<List<string>>() { };
+            values_lst = new List<List<string>>() { };
+            timestamp_lst = new List<long>() { };
+            List<Task<int>> tasks = new List<Task<int>>();
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+                measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+                values_lst.Add(new List<string>() { "test1", "test2" });
+                timestamp_lst.Add(timestamp);
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertAlignedStringRecordsAsync(device_id, measurements_lst, values_lst, timestamp_lst));
+                    device_id = new List<string>() { };
+                    measurements_lst = new List<List<string>>() { };
+                    values_lst = new List<List<string>>() { };
+                    timestamp_lst = new List<long>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            res.ShowTableNames();
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertAlignedStringRecords Passed!");
+        }
+        public async Task TestInsertAlignedRecordsOfOneDevice()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            string prefixPath = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurement_lst = new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4],
+                test_measurements[5],
+                test_measurements[6]
+            };
+            var data_type_lst = new List<TSDataType>()
+            {
+                TSDataType.BOOLEAN, TSDataType.INT32, TSDataType.INT64, TSDataType.DOUBLE, TSDataType.FLOAT,
+                TSDataType.TEXT
+            };
+            var encoding_lst = new List<TSEncoding>()
+            {
+                TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN,
+                TSEncoding.PLAIN
+            };
+            var compressor_lst = new List<Compressor>()
+            {
+                Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY,
+                Compressor.SNAPPY
+            };
+
+            status = await session_pool.CreateAlignedTimeseriesAsync(prefixPath, measurement_lst, data_type_lst, encoding_lst,
+                compressor_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurements_lst = new List<List<string>>() { };
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4]
+            });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4],
+                test_measurements[5],
+                test_measurements[6]
+            });
+            var values_lst = new List<List<object>>() { };
+            values_lst.Add(new List<object>() { true, (int)123 });
+            values_lst.Add(new List<object>() { true, (int)123, (long)456, (double)1.1 });
+            values_lst.Add(new List<object>()
+                {true, (int) 123, (long) 456, (double) 1.1, (float) 10001.1, "test_record"});
+            var timestamp_lst = new List<long>() { 1, 2, 3 };
+            var rowRecords = new List<RowRecord>() { };
+            for (var i = 0; i < 3; i++)
+            {
+                var rowRecord = new RowRecord(timestamp_lst[i], values_lst[i], measurements_lst[i]);
+                rowRecords.Add(rowRecord);
+            }
+            status = await session_pool.InsertAlignedRecordsOfOneDeviceAsync(device_id, rowRecords);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            rowRecords = new List<RowRecord>() { };
+            var tasks = new List<Task<int>>();
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                rowRecords.Add(new RowRecord(timestamp, new List<object>() { true, (int)123 },
+                    new List<string>() { test_measurements[1], test_measurements[2] }));
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertAlignedRecordsOfOneDeviceAsync(device_id, rowRecords));
+                    rowRecords = new List<RowRecord>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertAlignedRecordsOfOneDevice Passed!");
+        }
+        public async Task TestInsertAlignedStringRecordsOfOneDevice()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurements = new List<string>() { test_measurements[0], test_measurements[1], test_measurements[2] };
+            var data_type_lst = new List<TSDataType>() { TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT };
+            var encoding_lst = new List<TSEncoding>() { TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN };
+            var compressor_lst = new List<Compressor>() { Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY };
+            status = await session_pool.CreateAlignedTimeseriesAsync(device_id, measurements, data_type_lst, encoding_lst, compressor_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var measurements_lst = new List<List<string>>() { };
+            measurements_lst.Add(new List<string>() { test_measurements[0], test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>() { test_measurements[0], test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>() { test_measurements[0], test_measurements[1], test_measurements[2] });
+
+            var values_lst = new List<List<string>>() { };
+            values_lst.Add(new List<string>() { "test1", "test2", "test3" });
+            values_lst.Add(new List<string>() { "test4", "test5", "test6" });
+            values_lst.Add(new List<string>() { "test7", "test8", "test9" });
+
+            var timestamp_lst = new List<long>() { 1, 2, 3 };
+
+            status = await session_pool.InsertAlignedStringRecordsOfOneDeviceAsync(device_id, timestamp_lst, measurements_lst, values_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            // large data test
+            values_lst = new List<List<string>>() { };
+            var tasks = new List<Task<int>>();
+            measurements_lst = new List<List<string>>() { };
+            timestamp_lst = new List<long>() { };
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                values_lst.Add(new List<string>() { "test1", "test2" });
+                measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+                timestamp_lst.Add(timestamp);
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertAlignedStringRecordsOfOneDeviceAsync(device_id, timestamp_lst, measurements_lst, values_lst));
+                    values_lst = new List<List<string>>() { };
+                    measurements_lst = new List<List<string>>() { };
+                    timestamp_lst = new List<long>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertAlignedStringRecordsOfOneDevice Passed!");
+        }
+    }
+}
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedTablet.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedTablet.cs
new file mode 100644
index 0000000..51718b1
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedTablet.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Apache.IoTDB.DataStructure;
+
+namespace Apache.IoTDB.Samples
+{
+    public partial class SessionPoolTest
+    {
+        public async Task TestInsertAlignedTablet()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurement_lst = new List<string>
+                {   test_measurements[1],
+                    test_measurements[2],
+                    test_measurements[3]
+                };
+            var value_lst = new List<List<object>>
+            {
+                new() {"iotdb", true, (int) 12}, new() {"c#", false, (int) 13},
+                new() {"client", true, (int) 14}
+            };
+            var timestamp_lst = new List<long> { 1, 2, 3 };
+            var datatype_lst = new List<TSDataType> { TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32 };
+            var tablet = new Tablet(device_id, measurement_lst, datatype_lst, value_lst, timestamp_lst);
+            status = await session_pool.InsertAlignedTabletAsync(tablet);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<15");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            // large data test
+            value_lst = new List<List<object>>() { };
+            timestamp_lst = new List<long>() { };
+            var tasks = new List<Task<int>>();
+            var start_ms = DateTime.Now.Ticks / 10000;
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                timestamp_lst.Add(timestamp);
+                value_lst.Add(new List<object>() { "iotdb", true, (int)timestamp });
+                if (timestamp % fetch_size == 0)
+                {
+                    tablet = new Tablet(device_id, measurement_lst, datatype_lst, value_lst, timestamp_lst);
+                    tasks.Add(session_pool.InsertAlignedTabletAsync(tablet));
+                    value_lst = new List<List<object>>() { };
+                    timestamp_lst = new List<long>() { };
+                }
+            }
+            Console.WriteLine(tasks.Count);
+
+            Task.WaitAll(tasks.ToArray());
+            var end_ms = DateTime.Now.Ticks / 10000;
+            Console.WriteLine(string.Format("total tablet insert time is {0}", end_ms - start_ms));
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            res.ShowTableNames();
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertAlignedTablet Passed!");
+        }
+
+        public async Task TestInsertAlignedTablets()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var device_id = new List<string>()
+            {
+                string.Format("{0}.{1}", test_group_name, test_devices[1]),
+                string.Format("{0}.{1}", test_group_name, test_devices[2])
+            };
+            var measurements_lst = new List<List<string>>()
+            {
+                new() {test_measurements[1], test_measurements[2], test_measurements[3] },
+                new() {test_measurements[1], test_measurements[2], test_measurements[3] }
+            };
+            var values_lst = new List<List<List<object>>>()
+            {
+                new()
+                {
+                    new List<object>() {"iotdb", true, (int) 12}, new List<object>() {"c#", false, (int) 13},
+                    new List<object>() {"client", true, (int) 14}
+                },
+                new()
+                {
+                    new List<object>() {"iotdb_2", true, (int) 1}, new List<object>() {"c#_2", false, (int) 2},
+                    new List<object>() {"client_2", true, (int) 3}
+                }
+            };
+            var datatype_lst = new List<List<TSDataType>>()
+            {
+                new() {TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32},
+                new() {TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32}
+            };
+            var timestamp_lst = new List<List<long>>()
+                {new() {2, 1, 3}, new() {3, 1, 2}};
+            var tablets = new List<Tablet>() { };
+            for (var i = 0; i < device_id.Count; i++)
+            {
+                var tablet = new Tablet(device_id[i], measurements_lst[i], datatype_lst[i], values_lst[i], timestamp_lst[i]);
+                tablets.Add(tablet);
+            }
+
+            status = await session_pool.InsertAlignedTabletsAsync(tablets);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_devices[1]) + " where time<15");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            // large data test
+            var tasks = new List<Task<int>>();
+            // tablets = new List<Tablet>() { };
+            for (var timestamp = 4; timestamp <= processed_size * fetch_size; timestamp++)
+            {
+                var local_device_id = string.Format("{0}.{1}", test_group_name, test_devices[1]);
+                var local_measurements = new List<string>()
+                    {test_measurements[1], test_measurements[2], test_measurements[3]};
+                var local_value = new List<List<object>>() { new() { "iotdb", true, (int)timestamp } };
+                var local_data_type = new List<TSDataType>() { TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32 };
+                var local_timestamp = new List<long> { timestamp };
+                var tablet = new Tablet(local_device_id, local_measurements, local_data_type, local_value, local_timestamp);
+                tablets.Add(tablet);
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertAlignedTabletsAsync(tablets));
+                    tablets = new List<Tablet>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_devices[1]));
+            res.ShowTableNames();
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertAlignedTablets Passed!");
+        }
+    }
+}
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.Record.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.Record.cs
new file mode 100644
index 0000000..28e0401
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.Record.cs
@@ -0,0 +1,553 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Apache.IoTDB.DataStructure;
+
+namespace Apache.IoTDB.Samples
+{
+    public partial class SessionPoolTest
+    {
+
+        public async Task TestInsertRecord()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            int status;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]), TSDataType.TEXT,
+                TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[3]),
+                TSDataType.INT32, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var measures = new List<string>
+                {test_measurements[1], test_measurements[2], test_measurements[3]};
+            var values = new List<object> { "test_text", true, (int)123 };
+            var tasks = new List<Task<int>>();
+            var start_ms = DateTime.Now.Ticks / 10000;
+            for (var timestamp = 1; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                var rowRecord = new RowRecord(timestamp, values, measures);
+                var task = session_pool.InsertRecordAsync(
+                    string.Format("{0}.{1}", test_group_name, test_device), rowRecord);
+                tasks.Add(task);
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            var end_ms = DateTime.Now.Ticks / 10000;
+            Console.WriteLine(string.Format("total insert aligned record time is {0}", end_ms - start_ms));
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertRecordAsync Passed");
+        }
+        public async Task TestInsertStringRecord()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[0]), TSDataType.TEXT,
+                TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                TSDataType.TEXT, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.TEXT, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var measurements = new List<string>
+                {test_measurements[0], test_measurements[1], test_measurements[2]};
+            var values = new List<string> { "test_text1", "test_text2", "test_text3" };
+            var tasks = new List<Task<int>>();
+            var start_ms = DateTime.Now.Ticks / 10000;
+            for (var timestamp = 1; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                var task = session_pool.InsertStringRecordAsync(
+                    string.Format("{0}.{1}", test_group_name, test_device), measurements, values, timestamp);
+                tasks.Add(task);
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            var end_ms = DateTime.Now.Ticks / 10000;
+            Console.WriteLine(string.Format("total insert string record time is {0}", end_ms - start_ms));
+            var res = await session_pool.ExecuteQueryStatementAsync("select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            var res_cnt = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_cnt++;
+            }
+            Console.WriteLine(res_cnt + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_cnt == fetch_size * processed_size);
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertStringRecordAsync Passed");
+        }
+        public async Task TestInsertStrRecord()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                TSDataType.INT32, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.INT32, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var measures = new List<string> { test_measurements[1], test_measurements[2] };
+            var values = new List<object> { (int)1, (int)2 };
+            var rowRecord = new RowRecord(1, values, measures);
+            status = await session_pool.InsertRecordAsync(
+                string.Format("{0}.{1}", test_group_name, test_device), rowRecord);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<2");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+
+            var tasks = new List<Task<int>>();
+            // large data test
+            var rowRecords = new List<RowRecord>() { };
+            for (var timestamp = 2; timestamp <= fetch_size * processed_size; timestamp++)
+                rowRecords.Add(new RowRecord(timestamp, values, measures));
+
+            for (var timestamp = 2; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                var task = session_pool.InsertRecordAsync(
+                    string.Format("{0}.{1}", test_group_name, test_device), rowRecords[timestamp - 2]);
+                tasks.Add(task);
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertStrRecord Passed!");
+        }
+        public async Task TestInsertRecords()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.INT32, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[3]),
+                TSDataType.INT64, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[4]),
+                TSDataType.DOUBLE, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[5]),
+                TSDataType.FLOAT, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[6]), TSDataType.TEXT,
+                TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var device_id = new List<string>() { };
+            for (var i = 0; i < 3; i++) device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+
+            var measurements_lst = new List<List<string>>() { };
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4]
+            });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4],
+                test_measurements[5],
+                test_measurements[6]
+            });
+            var values_lst = new List<List<object>>() { };
+            values_lst.Add(new List<object>() { true, (int)123 });
+            values_lst.Add(new List<object>() { true, (int)123, (long)456, (double)1.1 });
+            values_lst.Add(new List<object>()
+                {true, (int) 123, (long) 456, (double) 1.1, (float) 10001.1, "test_record"});
+            var timestamp_lst = new List<long>() { 1, 2, 3 };
+            var rowRecords = new List<RowRecord>() { };
+            for (var i = 0; i < 3; i++)
+            {
+                var rowRecord = new RowRecord(timestamp_lst[i], values_lst[i], measurements_lst[i]);
+                rowRecords.Add(rowRecord);
+            }
+
+            status = await session_pool.InsertRecordsAsync(device_id, rowRecords);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            Console.WriteLine(status);
+
+            // large data test
+            device_id = new List<string>() { };
+            rowRecords = new List<RowRecord>() { };
+            var tasks = new List<Task<int>>();
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+                rowRecords.Add(new RowRecord(timestamp, new List<object>() { true, (int)123 },
+                    new List<string>() { test_measurements[1], test_measurements[2] }));
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertRecordsAsync(device_id, rowRecords));
+                    device_id = new List<string>() { };
+                    rowRecords = new List<RowRecord>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            res.ShowTableNames();
+            var record_count = fetch_size * processed_size;
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == record_count);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertRecords Passed!");
+        }
+        public async Task TestInsertStringRecords()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]), TSDataType.TEXT,
+                TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]), TSDataType.TEXT,
+                TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var device_id = new List<string>() { };
+            for (var i = 0; i < 3; i++) device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+
+            var measurements_lst = new List<List<string>>() { };
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            var values_lst = new List<List<string>>() { };
+            values_lst.Add(new List<string>() { "test1", "test2" });
+            values_lst.Add(new List<string>() { "test3", "test4" });
+            values_lst.Add(new List<string>() { "test5", "test6" });
+            var timestamp_lst = new List<long>() { 1, 2, 3 };
+
+            status = await session_pool.InsertStringRecordsAsync(device_id, measurements_lst, values_lst, timestamp_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+
+            // large data test
+            device_id = new List<string>() { };
+            measurements_lst = new List<List<string>>() { };
+            values_lst = new List<List<string>>() { };
+            timestamp_lst = new List<long>() { };
+            var tasks = new List<Task<int>>();
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+                measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+                values_lst.Add(new List<string>() { "test" + timestamp, "test" + timestamp });
+                timestamp_lst.Add(timestamp);
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertStringRecordsAsync(device_id, measurements_lst, values_lst, timestamp_lst));
+                    device_id = new List<string>() { };
+                    measurements_lst = new List<List<string>>() { };
+                    values_lst = new List<List<string>>() { };
+                    timestamp_lst = new List<long>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            res.ShowTableNames();
+            var record_count = fetch_size * processed_size;
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == record_count);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertStringRecords Passed!");
+        }
+        public async Task TestInsertRecordsOfOneDevice()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.INT32, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[3]),
+                TSDataType.INT64, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[4]),
+                TSDataType.DOUBLE, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[5]),
+                TSDataType.FLOAT, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[6]), TSDataType.TEXT,
+                TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurements_lst = new List<List<string>>() { };
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4]
+            });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4],
+                test_measurements[5],
+                test_measurements[6]
+            });
+            var values_lst = new List<List<object>>() { };
+            values_lst.Add(new List<object>() { true, (int)123 });
+            values_lst.Add(new List<object>() { true, (int)123, (long)456, (double)1.1 });
+            values_lst.Add(new List<object>()
+                {true, (int) 123, (long) 456, (double) 1.1, (float) 10001.1, "test_record"});
+            var timestamp_lst = new List<long>() { 1, 2, 3 };
+            var rowRecords = new List<RowRecord>() { };
+            for (var i = 0; i < 3; i++)
+            {
+                var rowRecord = new RowRecord(timestamp_lst[i], values_lst[i], measurements_lst[i]);
+                rowRecords.Add(rowRecord);
+            }
+
+            status = await session_pool.InsertRecordsOfOneDeviceAsync(device_id, rowRecords);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            // large data test
+            rowRecords = new List<RowRecord>() { };
+            var tasks = new List<Task<int>>();
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                rowRecords.Add(new RowRecord(timestamp, new List<object>() { true, (int)123 },
+                    new List<string>() { test_measurements[1], test_measurements[2] }));
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertRecordsOfOneDeviceAsync(device_id, rowRecords));
+                    rowRecords = new List<RowRecord>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertRecordsOfOneDevice Passed!");
+        }
+        public async Task TestInsertStringRecordsOfOneDevice()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[0]),
+                TSDataType.TEXT, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                TSDataType.TEXT, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.TEXT, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurements_lst = new List<List<string>>() { };
+            measurements_lst.Add(new List<string>() { test_measurements[0], test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>() { test_measurements[0], test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>() { test_measurements[0], test_measurements[1], test_measurements[2] });
+
+            var values_lst = new List<List<string>>() { };
+            values_lst.Add(new List<string>() { "test1", "test2", "test3" });
+            values_lst.Add(new List<string>() { "test4", "test5", "test6" });
+            values_lst.Add(new List<string>() { "test7", "test8", "test9" });
+
+            var timestamp_lst = new List<long>() { 1, 2, 3 };
+
+            status = await session_pool.InsertStringRecordsOfOneDeviceAsync(device_id, timestamp_lst, measurements_lst, values_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            // large data test
+            values_lst = new List<List<string>>() { };
+            var tasks = new List<Task<int>>();
+            measurements_lst = new List<List<string>>() { };
+            timestamp_lst = new List<long>() { };
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                values_lst.Add(new List<string>() { "test1", "test2" });
+                measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+                timestamp_lst.Add(timestamp);
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertStringRecordsOfOneDeviceAsync(device_id, timestamp_lst, measurements_lst, values_lst));
+                    values_lst = new List<List<string>>() { };
+                    measurements_lst = new List<List<string>>() { };
+                    timestamp_lst = new List<long>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertStringRecordsOfOneDevice Passed!");
+        }
+    }
+}
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.Tablet.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.Tablet.cs
new file mode 100644
index 0000000..62351fd
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.Tablet.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Apache.IoTDB.DataStructure;
+
+namespace Apache.IoTDB.Samples
+{
+    public partial class SessionPoolTest
+    {
+        public async Task TestInsertTablet()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurement_lst = new List<string>
+            {
+                    test_measurements[1],
+                    test_measurements[2],
+                    test_measurements[3]
+            };
+            var value_lst = new List<List<object>>
+            {
+                new() {"iotdb", true, (int) 12}, new() {"c#", false, (int) 13},
+                new() {"client", true, (int) 14}
+            };
+            var timestamp_lst = new List<long> { 1, 2, 3 };
+            var datatype_lst = new List<TSDataType> { TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32 };
+            var tablet = new Tablet(device_id, measurement_lst, datatype_lst, value_lst, timestamp_lst);
+            status = await session_pool.InsertTabletAsync(tablet);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                 "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<15");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            // large data test
+            value_lst = new List<List<object>>() { };
+            timestamp_lst = new List<long>() { };
+            var tasks = new List<Task<int>>();
+            var start_ms = DateTime.Now.Ticks / 10000;
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                timestamp_lst.Add(timestamp);
+                value_lst.Add(new List<object>() { "iotdb", true, (int)timestamp });
+                if (timestamp % fetch_size == 0)
+                {
+                    tablet = new Tablet(device_id, measurement_lst, datatype_lst, value_lst, timestamp_lst);
+                    tasks.Add(session_pool.InsertTabletAsync(tablet));
+                    value_lst = new List<List<object>>() { };
+                    timestamp_lst = new List<long>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            var end_ms = DateTime.Now.Ticks / 10000;
+            Console.WriteLine(string.Format("total tablet insert time is {0}", end_ms - start_ms));
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            res.ShowTableNames();
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertTablet Passed!");
+        }
+
+        public async Task TestInsertTablets()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var device_id = new List<string>()
+            {
+                string.Format("{0}.{1}", test_group_name, test_devices[1]),
+                string.Format("{0}.{1}", test_group_name, test_devices[2])
+            };
+            var measurements_lst = new List<List<string>>()
+            {
+                new() {test_measurements[1], test_measurements[2], test_measurements[3]},
+                new() {test_measurements[1], test_measurements[2], test_measurements[3]}
+            };
+            var values_lst = new List<List<List<object>>>()
+            {
+                new()
+                {
+                    new List<object>() {"iotdb", true, (int) 12}, new List<object>() {"c#", false, (int) 13},
+                    new List<object>() {"client", true, (int) 14}
+                },
+                new()
+                {
+                    new List<object>() {"iotdb_2", true, (int) 1}, new List<object>() {"c#_2", false, (int) 2},
+                    new List<object>() {"client_2", true, (int) 3}
+                }
+            };
+            var datatype_lst = new List<List<TSDataType>>()
+            {
+                new() {TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32},
+                new() {TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32}
+            };
+            var timestamp_lst = new List<List<long>>()
+                {new() {2, 1, 3}, new() {3, 1, 2}};
+            var tablets = new List<Tablet>() { };
+            for (var i = 0; i < device_id.Count; i++)
+            {
+                var tablet = new Tablet(device_id[i], measurements_lst[i], datatype_lst[i], values_lst[i], timestamp_lst[i]);
+                tablets.Add(tablet);
+            }
+
+            status = await session_pool.InsertTabletsAsync(tablets);
+            // System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_devices[1]) + " where time<15");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            // large data test
+
+            var tasks = new List<Task<int>>();
+            // tablets = new List<Tablet>();
+            for (var timestamp = 4; timestamp <= processed_size * fetch_size; timestamp++)
+            {
+                var local_device_id = string.Format("{0}.{1}", test_group_name, test_devices[1]);
+                var local_measurements = new List<string>()
+                    {test_measurements[1], test_measurements[2], test_measurements[3]};
+                var local_value = new List<List<object>>() { new() { "iotdb", true, (int)timestamp } };
+                var local_timestamp = new List<long> { timestamp };
+                var local_data_type = new List<TSDataType> { TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32 };
+                var tablet = new Tablet(local_device_id, local_measurements, local_data_type, local_value, local_timestamp);
+                tablets.Add(tablet);
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.InsertTabletsAsync(tablets));
+                    tablets = new List<Tablet>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_devices[1]));
+            res.ShowTableNames();
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            Console.WriteLine(res_count + " " + fetch_size * processed_size);
+            System.Diagnostics.Debug.Assert(res_count == fetch_size * processed_size);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertTablets Passed!");
+        }
+        public async Task TestInsertTabletWithNullValue()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurements = new List<string>() { test_measurements[1], test_measurements[2], test_measurements[3] };
+            var values = new List<List<object>>()
+            {
+                new List<object>() {null, true, (int) 12}, new List<object>() {"c#", null, (int) 13},
+                new List<object>() {"client", true, null}
+            };
+            var datatype = new List<TSDataType>() { TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32 };
+            var timestamp = new List<long>() { 2, 1, 3 };
+            var tablet = new Tablet(device_id, measurements, datatype, values, timestamp);
+            status = await session_pool.InsertTabletAsync(tablet);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            res.ShowTableNames();
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                Console.WriteLine(res.Next());
+                res_count += 1;
+            }
+
+            await res.Close();
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestInsertTabletsWithNullValue Passed!");
+        }
+    }
+}
diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.Template.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.Template.cs
new file mode 100644
index 0000000..80fbda6
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.Template.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Apache.IoTDB.DataStructure;
+namespace Apache.IoTDB.Samples
+{
+    public partial class SessionPoolTest
+    {
+        public async Task TestCreateAndDropSchemaTemplate()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DropSchemaTemplateAsync(test_template_name);
+
+            MeasurementNode node1 = new MeasurementNode(test_measurements[1], TSDataType.INT32, TSEncoding.PLAIN, Compressor.SNAPPY);
+            MeasurementNode node2 = new MeasurementNode(test_measurements[2], TSDataType.INT64, TSEncoding.PLAIN, Compressor.SNAPPY);
+            MeasurementNode node3 = new MeasurementNode(test_measurements[3], TSDataType.DOUBLE, TSEncoding.PLAIN, Compressor.SNAPPY);
+            MeasurementNode node4 = new MeasurementNode(test_measurements[4], TSDataType.FLOAT, TSEncoding.PLAIN, Compressor.SNAPPY);
+
+            Template template = new Template(test_template_name);
+            template.addToTemplate(node1);
+            template.addToTemplate(node2);
+            template.addToTemplate(node3);
+            template.addToTemplate(node4);
+
+            status = await session_pool.CreateSchemaTemplateAsync(template);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var templates = await session_pool.ShowAllTemplatesAsync();
+            foreach (var t in templates)
+            {
+                Console.WriteLine("template name :\t{0}", t);
+            }
+            status = await session_pool.DropSchemaTemplateAsync(test_template_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+            Console.WriteLine("TestCreateAndDropSchemaTemplate Passed!");
+        }
+
+        public async Task TestSetAndUnsetSchemaTemplate()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.UnsetSchemaTemplateAsync(string.Format("{0}.{1}", test_group_name, test_device), "template");
+            await session_pool.DropSchemaTemplateAsync(test_template_name);
+
+            MeasurementNode node1 = new MeasurementNode(test_measurements[1], TSDataType.INT32, TSEncoding.PLAIN, Compressor.SNAPPY);
+            MeasurementNode node2 = new MeasurementNode(test_measurements[2], TSDataType.INT64, TSEncoding.PLAIN, Compressor.SNAPPY);
+            MeasurementNode node3 = new MeasurementNode(test_measurements[3], TSDataType.DOUBLE, TSEncoding.PLAIN, Compressor.SNAPPY);
+            MeasurementNode node4 = new MeasurementNode(test_measurements[4], TSDataType.FLOAT, TSEncoding.PLAIN, Compressor.SNAPPY);
+
+            Template template = new Template(test_template_name);
+            template.addToTemplate(node1);
+            template.addToTemplate(node2);
+            template.addToTemplate(node3);
+            template.addToTemplate(node4);
+
+            status = await session_pool.CreateSchemaTemplateAsync(template);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.SetSchemaTemplateAsync(test_template_name, string.Format("{0}.{1}", test_group_name, test_device));
+            var paths = await session_pool.ShowPathsTemplateSetOnAsync(test_template_name);
+            foreach (var p in paths)
+            {
+                Console.WriteLine("path :\t{0}", p);
+            }
+            status = await session_pool.UnsetSchemaTemplateAsync(string.Format("{0}.{1}", test_group_name, test_device), test_template_name);
+            status = await session_pool.DropSchemaTemplateAsync(test_template_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+            Console.WriteLine("TestSetAndUnsetSchemaTemplate Passed!");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.TestNetwork.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.TestNetwork.cs
new file mode 100644
index 0000000..a4f3ffc
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.TestNetwork.cs
@@ -0,0 +1,335 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Apache.IoTDB.DataStructure;
+namespace Apache.IoTDB.Samples
+{
+    public partial class SessionPoolTest
+    {
+        public async Task TestTestInsertRecord()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            int status;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]), TSDataType.TEXT,
+                TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[3]),
+                TSDataType.INT32, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var measures = new List<string>
+                {
+                    test_measurements[1], test_measurements[2], test_measurements[3]
+                };
+            var values = new List<object> { "test_text", true, (int)123 };
+            var tasks = new List<Task<int>>();
+            var start_ms = DateTime.Now.Ticks / 10000;
+            for (var timestamp = 1; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                var rowRecord = new RowRecord(timestamp, values, measures);
+                var task = session_pool.TestInsertRecordAsync(
+                    string.Format("{0}.{1}", test_group_name, test_device), rowRecord);
+                tasks.Add(task);
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            var end_ms = DateTime.Now.Ticks / 10000;
+            Console.WriteLine(string.Format("total insert record time is {0}", end_ms - start_ms));
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+            Console.WriteLine("TestTestInsertRecordAsync Passed");
+        }
+
+        public async Task TestTestInsertRecords()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var status = 0;
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.INT32, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[3]),
+                TSDataType.INT64, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[4]),
+                TSDataType.DOUBLE, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[5]),
+                TSDataType.FLOAT, TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[6]), TSDataType.TEXT,
+                TSEncoding.PLAIN, Compressor.SNAPPY);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var device_id = new List<string>() { };
+            for (var i = 0; i < 3; i++) device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+
+            var measurements_lst = new List<List<string>>() { };
+            measurements_lst.Add(new List<string>() { test_measurements[1], test_measurements[2] });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4]
+            });
+            measurements_lst.Add(new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4],
+                test_measurements[5],
+                test_measurements[6]
+            });
+            var values_lst = new List<List<object>>() { };
+            values_lst.Add(new List<object>() { true, (int)123 });
+            values_lst.Add(new List<object>() { true, (int)123, (long)456, (double)1.1 });
+            values_lst.Add(new List<object>()
+                {true, (int) 123, (long) 456, (double) 1.1, (float) 10001.1, "test_record"});
+            var timestamp_lst = new List<long>() { 1, 2, 3 };
+            var rowRecords = new List<RowRecord>() { };
+            for (var i = 0; i < 3; i++)
+            {
+                var rowRecord = new RowRecord(timestamp_lst[i], values_lst[i], measurements_lst[i]);
+                rowRecords.Add(rowRecord);
+            }
+
+            status = await session_pool.TestInsertRecordsAsync(device_id, rowRecords);
+            // System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+
+            // large data test
+            device_id = new List<string>() { };
+            rowRecords = new List<RowRecord>() { };
+            var tasks = new List<Task<int>>();
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                device_id.Add(string.Format("{0}.{1}", test_group_name, test_device));
+                rowRecords.Add(new RowRecord(timestamp, new List<object>() { true, (int)123 },
+                    new List<string>() { test_measurements[1], test_measurements[2] }));
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.TestInsertRecordsAsync(device_id, rowRecords));
+                    device_id = new List<string>() { };
+                    rowRecords = new List<RowRecord>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            res.ShowTableNames();
+            var record_count = fetch_size * processed_size;
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            System.Diagnostics.Debug.Assert(res_count == 0);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestTestInsertRecords Passed!");
+        }
+
+        public async Task TestTestInsertTablet()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurement_lst = new List<string>
+                {   test_measurements[1],
+                    test_measurements[2],
+                    test_measurements[3]
+                };
+            var value_lst = new List<List<object>>
+            {
+                new() {"iotdb", true, (int) 12}, new() {"c#", false, (int) 13},
+                new() {"client", true, (int) 14}
+            };
+            var timestamp_lst = new List<long> { 2, 1, 3 };
+            var datatype_lst = new List<TSDataType> { TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32 };
+            var tablet = new Tablet(device_id, measurement_lst, datatype_lst, value_lst, timestamp_lst);
+            status = await session_pool.TestInsertTabletAsync(tablet);
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<15");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            // large data test
+            value_lst = new List<List<object>>() { };
+            timestamp_lst = new List<long>() { };
+            var tasks = new List<Task<int>>();
+            var start_ms = DateTime.Now.Ticks / 10000;
+            for (var timestamp = 4; timestamp <= fetch_size * processed_size; timestamp++)
+            {
+                timestamp_lst.Add(timestamp);
+                value_lst.Add(new List<object>() { "iotdb", true, (int)timestamp });
+                if (timestamp % (fetch_size / 32) == 0)
+                {
+                    tablet = new Tablet(device_id, measurement_lst, datatype_lst, value_lst, timestamp_lst);
+                    tasks.Add(session_pool.TestInsertTabletAsync(tablet));
+                    value_lst = new List<List<object>>() { };
+                    timestamp_lst = new List<long>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            var end_ms = DateTime.Now.Ticks / 10000;
+            Console.WriteLine(string.Format("total tablet insert time is {0}", end_ms - start_ms));
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device));
+            res.ShowTableNames();
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            System.Diagnostics.Debug.Assert(res_count == 0);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestTestInsertTablet Passed!");
+        }
+
+        public async Task TestTestInsertTablets()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var device_id = new List<string>()
+            {
+                string.Format("{0}.{1}", test_group_name, test_devices[1]),
+                string.Format("{0}.{1}", test_group_name, test_devices[2])
+            };
+            var measurements_lst = new List<List<string>>()
+            {
+                new() {test_measurements[1], test_measurements[2], test_measurements[3]},
+                new() {test_measurements[1], test_measurements[2], test_measurements[3]}
+            };
+            var values_lst = new List<List<List<object>>>()
+            {
+                new()
+                {
+                    new List<object>() {"iotdb", true, (int) 12}, new List<object>() {"c#", false, (int) 13},
+                    new List<object>() {"client", true, (int) 14}
+                },
+                new()
+                {
+                    new List<object>() {"iotdb_2", true, (int) 1}, new List<object>() {"c#_2", false, (int) 2},
+                    new List<object>() {"client_2", true, (int) 3}
+                }
+            };
+            var datatype_lst = new List<List<TSDataType>>()
+            {
+                new() {TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32},
+                new() {TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32}
+            };
+            var timestamp_lst = new List<List<long>>()
+                {new() {2, 1, 3}, new() {3, 1, 2}};
+            var tablets = new List<Tablet>() { };
+            for (var i = 0; i < device_id.Count; i++)
+            {
+                var tablet = new Tablet(device_id[i], measurements_lst[i], datatype_lst[i], values_lst[i], timestamp_lst[i]);
+                tablets.Add(tablet);
+            }
+
+            status = await session_pool.TestInsertTabletsAsync(tablets);
+            // System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_devices[1]) + " where time<15");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+            await res.Close();
+
+            // large data test
+
+            var tasks = new List<Task<int>>();
+            for (var timestamp = 4; timestamp <= processed_size * fetch_size; timestamp++)
+            {
+                var local_device_id = string.Format("{0}.{1}", test_group_name, test_devices[1]);
+                var local_measurements = new List<string>()
+                    {test_measurements[1], test_measurements[2], test_measurements[3]};
+                var local_value = new List<List<object>>() { new() { "iotdb", true, (int)timestamp } };
+                var local_timestamp = new List<long> { timestamp };
+                var local_data_type = new List<TSDataType> { TSDataType.TEXT, TSDataType.BOOLEAN, TSDataType.INT32 };
+                var tablet = new Tablet(local_device_id, local_measurements, local_data_type, local_value, local_timestamp);
+                tablets.Add(tablet);
+                if (timestamp % fetch_size == 0)
+                {
+                    tasks.Add(session_pool.TestInsertTabletsAsync(tablets));
+                    tablets = new List<Tablet>() { };
+                }
+            }
+
+            Task.WaitAll(tasks.ToArray());
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_devices[1]));
+            res.ShowTableNames();
+            var res_count = 0;
+            while (res.HasNext())
+            {
+                res.Next();
+                res_count += 1;
+            }
+
+            await res.Close();
+            System.Diagnostics.Debug.Assert(res_count == 0);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestTestInsertTablets Passed!");
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.TimeSeries.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.TimeSeries.cs
new file mode 100644
index 0000000..1fd6197
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.TimeSeries.cs
@@ -0,0 +1,178 @@
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Apache.IoTDB.DataStructure;
+namespace Apache.IoTDB.Samples
+{
+    public partial class SessionPoolTest
+    {
+        public async Task TestCreateMultiTimeSeries()
+        {
+            // by Luzhan
+            var session_pool = new SessionPool(host, port, user, passwd, pool_size);
+            await session_pool.Open(false);
+            var status = 0;
+            if (debug) session_pool.OpenDebugMode();
+
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var measurement_lst = new List<int> { 1, 2, 3, 4, 5, 6 };
+            var ts_path_lst = new List<string>(measurement_lst.ConvertAll(
+                (measurement) => string.Format("{0}.{1}.{2}{3}", test_group_name, test_device, test_measurement, measurement)));
+            var data_type_lst = new List<TSDataType>()
+            {
+                TSDataType.BOOLEAN, TSDataType.INT32, TSDataType.INT64, TSDataType.FLOAT, TSDataType.DOUBLE,
+                TSDataType.TEXT
+            };
+            var encoding_lst = new List<TSEncoding>()
+            {
+                TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN,
+                TSEncoding.PLAIN
+            };
+            var compressor_lst = new List<Compressor>()
+            {
+                Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY,
+                Compressor.SNAPPY
+            };
+            status = await session_pool.CreateMultiTimeSeriesAsync(ts_path_lst, data_type_lst, encoding_lst,
+                compressor_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestCreateMultiTimeSeries Passed!");
+        }
+
+        public async Task TestDeleteTimeSeries()
+        {
+            var session_pool = new SessionPool(host, port, user, passwd, pool_size);
+            await session_pool.Open(false);
+            var status = 0;
+            if (debug) session_pool.OpenDebugMode();
+
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var measurement_lst = new List<int> { 1, 2, 3, 4, 5, 6 };
+            var ts_path_lst = new List<string>(measurement_lst.ConvertAll(
+                (measurement) => string.Format("{0}.{1}.{2}{3}", test_group_name, test_device, test_measurement, measurement)));
+            var data_type_lst = new List<TSDataType>()
+            {
+                TSDataType.BOOLEAN, TSDataType.INT32, TSDataType.INT64, TSDataType.FLOAT, TSDataType.DOUBLE,
+                TSDataType.TEXT
+            };
+            var encoding_lst = new List<TSEncoding>()
+            {
+                TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN,
+                TSEncoding.PLAIN
+            };
+            var compressor_lst = new List<Compressor>()
+            {
+                Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY,
+                Compressor.SNAPPY
+            };
+            status = await session_pool.CreateMultiTimeSeriesAsync(ts_path_lst, data_type_lst, encoding_lst,
+                compressor_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.DeleteTimeSeriesAsync(ts_path_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+            Console.WriteLine("TestDeleteTimeSeries Passed!");
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+        }
+        public async Task TestCreateTimeSeries()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.SNAPPY) == 0);
+            System.Diagnostics.Debug.Assert(await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.INT32, TSEncoding.PLAIN, Compressor.SNAPPY) == 0);
+            System.Diagnostics.Debug.Assert(await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[3]),
+                TSDataType.INT64, TSEncoding.PLAIN, Compressor.SNAPPY) == 0);
+            System.Diagnostics.Debug.Assert(await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[4]),
+                TSDataType.FLOAT, TSEncoding.PLAIN, Compressor.SNAPPY) == 0);
+            System.Diagnostics.Debug.Assert(await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[5]),
+                TSDataType.DOUBLE, TSEncoding.PLAIN, Compressor.SNAPPY) == 0);
+            System.Diagnostics.Debug.Assert(await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[6]),
+                TSDataType.TEXT, TSEncoding.PLAIN, Compressor.SNAPPY) == 0);
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.Close();
+            Console.WriteLine("TestCreateTimeSeries Passed!");
+        }
+
+        public async Task TestCreateAlignedTimeseries()
+        {
+            var session_pool = new SessionPool(host, port, user, passwd, pool_size);
+            await session_pool.Open(false);
+            var status = 0;
+            if (debug) session_pool.OpenDebugMode();
+
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            string prefixPath = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurement_lst = new List<string>()
+            {
+                test_measurements[1],
+                test_measurements[2],
+                test_measurements[3],
+                test_measurements[4],
+                test_measurements[5],
+                test_measurements[6]
+            };
+            var data_type_lst = new List<TSDataType>()
+            {
+                TSDataType.BOOLEAN, TSDataType.INT32, TSDataType.INT64, TSDataType.FLOAT, TSDataType.DOUBLE,
+                TSDataType.TEXT
+            };
+            var encoding_lst = new List<TSEncoding>()
+            {
+                TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN, TSEncoding.PLAIN,
+                TSEncoding.PLAIN
+            };
+            var compressor_lst = new List<Compressor>()
+            {
+                Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY, Compressor.SNAPPY,
+                Compressor.SNAPPY
+            };
+            status = await session_pool.CreateAlignedTimeseriesAsync(prefixPath, measurement_lst, data_type_lst, encoding_lst,
+                compressor_lst);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestCreateAlignedTimeSeries Passed!");
+        }
+        public async Task TestCheckTimeSeriesExists()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.SNAPPY);
+            var ifExist_1 = await session_pool.CheckTimeSeriesExistsAsync(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]));
+            var ifExist_2 = await session_pool.CheckTimeSeriesExistsAsync(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]));
+            System.Diagnostics.Debug.Assert(ifExist_1 == true && ifExist_2 == false);
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestCheckTimeSeriesExists Passed!");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.cs
new file mode 100644
index 0000000..e016185
--- /dev/null
+++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.cs
@@ -0,0 +1,500 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Apache.IoTDB.Data;
+using Apache.IoTDB.DataStructure;
+using ConsoleTableExt;
+using System.Net.Sockets;
+
+namespace Apache.IoTDB.Samples
+{
+    public partial class SessionPoolTest
+    {
+        public string host = "localhost";
+        public int port = 6667;
+        public string user = "root";
+        public string passwd = "root";
+        public int fetch_size = 500;
+        public int processed_size = 4;
+        public bool debug = false;
+        private int pool_size = 2;
+        public static string test_template_name = "TEST_CSHARP_CLIENT_TEMPLATE_97209";
+        public static string test_group_name = "root.TEST_CSHARP_CLIENT_GROUP_97209";
+        public static string test_device = "TEST_CSHARP_CLIENT_DEVICE";
+        public static string test_measurement = "TEST_CSHARP_CLIENT_TS";
+        public static List<int> device_count = new List<int>() { 0, 1, 2, 3 };
+        public static List<int> measurement_count = new List<int>() { 0, 1, 2, 3, 4, 5, 6 };
+        public static List<string> test_devices = new List<string>(
+            device_count.ConvertAll(x => test_device + x.ToString()).ToArray()
+        );
+        public List<string> test_measurements = new List<string>(
+            measurement_count.ConvertAll(x => test_measurement + x.ToString()).ToArray()
+        );
+
+
+        public SessionPoolTest(string _host = "localhost")
+        {
+            host = _host;
+        }
+
+        public async Task Test()
+        {
+            await TestInsertOneRecord();
+
+            await TestInsertAlignedRecord();
+
+            await TestInsertAlignedRecords();
+
+            await TestInsertAlignedStringRecords();
+
+            await TestInsertAlignedStringRecordsOfOneDevice();
+
+            await TestInsertStringRecord();
+
+            await TestInsertAlignedStringRecord();
+
+            await TestInsertStringRecords();
+
+            await TestInsertStringRecordsOfOneDevice();
+
+            await TestInsertAlignedRecordsOfOneDevice();
+
+            await TestInsertAlignedTablet();
+
+            await TestInsertAlignedTablets();
+
+            await TestInsertRecord();
+
+            await TestCreateMultiTimeSeries();
+
+            await TestInsertStrRecord();
+
+            await TestInsertRecords();
+
+            await TestInsertRecordsOfOneDevice();
+
+            await TestInsertTablet();
+
+            await TestInsertTabletWithNullValue();
+
+            await TestInsertTablets();
+
+            await TestSetAndUnsetSchemaTemplate();
+
+            await TestCreateAlignedTimeseries();
+
+            await TestCreateAndDropSchemaTemplate();
+
+            await TestGetTimeZone();
+
+            await TestSetAndDeleteStorageGroup();
+
+            await TestCreateTimeSeries();
+
+            await TestDeleteTimeSeries();
+
+            await TestDeleteStorageGroups();
+
+            await TestCheckTimeSeriesExists();
+
+            await TestSetTimeZone();
+
+            await TestDeleteData();
+
+            await TestNonSql();
+
+            await TestRawDataQuery();
+
+            await TestLastDataQuery();
+
+            await TestSqlQuery();
+
+            await TestNonSqlBy_ADO();
+        }
+        public async Task TestInsertOneRecord()
+        {
+            var session_pool = new SessionPool(host, port, 1);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            var status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[0]),
+                TSDataType.TEXT, TSEncoding.PLAIN, Compressor.SNAPPY);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                TSDataType.TEXT, TSEncoding.PLAIN, Compressor.SNAPPY);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.TEXT, TSEncoding.PLAIN, Compressor.SNAPPY);
+            var rowRecord = new RowRecord(1668404120807, new() { "1111111", "22222", "333333" }, new() { test_measurements[0], test_measurements[1], test_measurements[2] });
+            status = await session_pool.InsertRecordsAsync(new List<string>() { string.Format("{0}.{1}", test_group_name, test_device) }, new List<RowRecord>() { rowRecord });
+        }
+        public async Task TestGetTimeZone()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            var time_zone = await session_pool.GetTimeZone();
+            System.Diagnostics.Debug.Assert(time_zone == "UTC+08:00");
+            await session_pool.Close();
+            Console.WriteLine("TestGetTimeZone Passed!");
+        }
+
+
+
+        public async Task TestSetAndDeleteStorageGroup()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(
+                await session_pool.SetStorageGroup(test_group_name) == 0);
+            System.Diagnostics.Debug.Assert(
+                await session_pool.DeleteStorageGroupAsync(test_group_name) == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestSetAndDeleteStorageGroup Passed!");
+        }
+
+        public async Task TestDeleteStorageGroups()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            await session_pool.SetStorageGroup(string.Format("{0}{1}", test_group_name, "_01"));
+            await session_pool.SetStorageGroup(string.Format("{0}{1}", test_group_name, "_02"));
+            await session_pool.SetStorageGroup(string.Format("{0}{1}", test_group_name, "_03"));
+            await session_pool.SetStorageGroup(string.Format("{0}{1}", test_group_name, "_04"));
+            var group_names = new List<string>() { };
+            group_names.Add(string.Format("{0}{1}", test_group_name, "_01"));
+            group_names.Add(string.Format("{0}{1}", test_group_name, "_02"));
+            group_names.Add(string.Format("{0}{1}", test_group_name, "_03"));
+            group_names.Add(string.Format("{0}{1}", test_group_name, "_04"));
+            System.Diagnostics.Debug.Assert(await session_pool.DeleteStorageGroupsAsync(group_names) == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestDeleteStorageGroups Passed!");
+        }
+
+
+        public async Task TestSetTimeZone()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            await session_pool.SetTimeZone("GMT+8:00");
+            System.Diagnostics.Debug.Assert(await session_pool.GetTimeZone() == "GMT+8:00");
+            await session_pool.Close();
+            Console.WriteLine("TestSetTimeZone Passed!");
+        }
+
+        public async Task TestDeleteData()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]), TSDataType.TEXT,
+                TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+                TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.CreateTimeSeries(
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[3]),
+                TSDataType.INT32, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var measures = new List<string>
+            {
+                test_measurements[1], test_measurements[2], test_measurements[3]
+            };
+            var values = new List<object> { "test_text", true, (int)123 };
+            status = await session_pool.InsertRecordAsync(
+                string.Format("{0}.{1}", test_group_name, test_device), new RowRecord(1, values, measures));
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.InsertRecordAsync(
+                string.Format("{0}.{1}", test_group_name, test_device), new RowRecord(2, values, measures));
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.InsertRecordAsync(
+                string.Format("{0}.{1}", test_group_name, test_device), new RowRecord(3, values, measures));
+            System.Diagnostics.Debug.Assert(status == 0);
+            status = await session_pool.InsertRecordAsync(
+                string.Format("{0}.{1}", test_group_name, test_device), new RowRecord(4, values, measures));
+            System.Diagnostics.Debug.Assert(status == 0);
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            var ts_path_lst = new List<string>()
+            {
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[1]),
+                string.Format("{0}.{1}.{2}", test_group_name, test_device, test_measurements[2]),
+            };
+            await session_pool.DeleteDataAsync(ts_path_lst, 2, 3);
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestDeleteData Passed!");
+        }
+
+        public async Task TestNonSql()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "create timeseries " + string.Format("{0}.{1}", test_group_name, test_device) + ".status with datatype=BOOLEAN,encoding=PLAIN");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "create timeseries " + string.Format("{0}.{1}", test_group_name, test_device) + ".temperature with datatype=FLOAT,encoding=PLAIN");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "create timeseries " + string.Format("{0}.{1}", test_group_name, test_device) + ".hardware with datatype=TEXT,encoding=PLAIN");
+            status = await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (4, false, 20, 'yxl')");
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (5, true, 12, 'myy')");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (6, true, 21, 'lz')");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, hardware) VALUES (7, true,'lz')");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, hardware) VALUES (7, true,'lz')");
+            var res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("TestNonSql Passed");
+        }
+
+        public async Task TestNonSqlBy_ADO()
+        {
+            var cnts = new IoTDB.Data.IoTDBConnectionStringBuilder();
+            cnts.DataSource = host;
+            cnts.TimeOut = (int)TimeSpan.FromSeconds(20).TotalMilliseconds;
+            var cnt = new IoTDB.Data.IoTDBConnection(cnts.ConnectionString);
+            await cnt.OpenAsync();
+            var session_pool = cnt.SessionPool;
+            System.Diagnostics.Debug.Assert(cnt.State == System.Data.ConnectionState.Open);
+            var status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await cnt.CreateCommand(
+                 "create timeseries " + string.Format("{0}.{1}", test_group_name, test_device) + ".status with datatype=BOOLEAN,encoding=PLAIN").ExecuteNonQueryAsync();
+            await cnt.CreateCommand(
+                "create timeseries " + string.Format("{0}.{1}", test_group_name, test_device) + ".temperature with datatype=FLOAT,encoding=PLAIN").ExecuteNonQueryAsync();
+            await cnt.CreateCommand(
+                "create timeseries " + string.Format("{0}.{1}", test_group_name, test_device) + ".hardware with datatype=TEXT,encoding=PLAIN").ExecuteNonQueryAsync();
+
+            status = await cnt.CreateCommand(
+    "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (3, false, 20, '1yxl')").ExecuteNonQueryAsync();
+            status = await cnt.CreateCommand(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (4, false, 20, 'yxl')").ExecuteNonQueryAsync();
+            System.Diagnostics.Debug.Assert(status == 0);
+            await cnt.CreateCommand(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (5, true, 12, 'myy')").ExecuteNonQueryAsync();
+            await cnt.CreateCommand(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (6, true, 21, 'lz')").ExecuteNonQueryAsync();
+            await cnt.CreateCommand(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, hardware) VALUES (7, true,'lz')").ExecuteNonQueryAsync();
+            await cnt.CreateCommand(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, hardware) VALUES (7, true,'lz')").ExecuteNonQueryAsync();
+            var reader = await cnt.CreateCommand(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10").ExecuteReaderAsync();
+            ConsoleTableBuilder.From(reader.ToDataTable()).WithFormatter(0, fc => $"{fc:yyyy-MM-dd HH:mm:ss.fff}").WithFormat(ConsoleTableBuilderFormat.Default).ExportAndWriteLine();
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await cnt.CloseAsync();
+
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            Console.WriteLine("TestNonSqlBy_ADO Passed");
+        }
+
+        public async Task TestSqlQuery()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "create timeseries " + string.Format("{0}.{1}", test_group_name, test_device) + ".status with datatype=BOOLEAN,encoding=PLAIN");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "create timeseries " + string.Format("{0}.{1}", test_group_name, test_device) + ".temperature with datatype=FLOAT,encoding=PLAIN");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "create timeseries " + string.Format("{0}.{1}", test_group_name, test_device) + ".hardware with datatype=TEXT,encoding=PLAIN");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (4, false, 20, 'yxl')");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (5, true, 12, 'myy')");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, temperature, hardware) VALUES (6, true, 21, 'lz')");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, hardware) VALUES (7, true,'lz')");
+            await session_pool.ExecuteNonQueryStatementAsync(
+                "insert into " + string.Format("{0}.{1}", test_group_name, test_device) + "(timestamp, status, hardware) VALUES (7, true,'lz')");
+
+            var res = await session_pool.ExecuteQueryStatementAsync("show timeseries root");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            Console.WriteLine("SHOW TIMESERIES ROOT sql passed!");
+            res = await session_pool.ExecuteQueryStatementAsync("show devices");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            Console.WriteLine("SHOW DEVICES sql passed!");
+            res = await session_pool.ExecuteQueryStatementAsync("COUNT TIMESERIES root");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            Console.WriteLine("COUNT TIMESERIES root sql Passed");
+            res = await session_pool.ExecuteQueryStatementAsync("select * from root.ln.wf01 where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            Console.WriteLine("SELECT sql Passed");
+            res = await session_pool.ExecuteQueryStatementAsync(
+                "select * from " + string.Format("{0}.{1}", test_group_name, test_device) + " where time<10");
+            res.ShowTableNames();
+            while (res.HasNext()) Console.WriteLine(res.Next());
+
+            await res.Close();
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("SELECT sql Passed");
+        }
+        public async Task TestRawDataQuery()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurements = new List<string> { test_measurements[0], test_measurements[1] };
+            var data_type_lst = new List<TSDataType> { TSDataType.BOOLEAN, TSDataType.FLOAT };
+            var encoding_lst = new List<TSEncoding> { TSEncoding.PLAIN, TSEncoding.PLAIN };
+            var compressor_lst = new List<Compressor> { Compressor.SNAPPY, Compressor.SNAPPY };
+            status = await session_pool.CreateAlignedTimeseriesAsync(device_id, measurements, data_type_lst, encoding_lst, compressor_lst);
+
+            var records = new List<RowRecord>();
+            var values = new List<object>() { true, 20.0f };
+            var device_id_lst = new List<string>() { };
+            for (int i = 1; i <= fetch_size * processed_size; i++)
+            {
+                var record = new RowRecord(i, values, measurements);
+                records.Add(record);
+                device_id_lst.Add(device_id);
+            }
+            status = await session_pool.InsertAlignedRecordsAsync(device_id_lst, records);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var paths = new List<string>() { string.Format("{0}.{1}", device_id, test_measurements[0]), string.Format("{0}.{1}", device_id, test_measurements[1]) };
+
+            var res = await session_pool.ExecuteRawDataQuery(paths, 10, fetch_size * processed_size);
+            var count = 0;
+            while (res.HasNext())
+            {
+                var record = res.Next();
+                count++;
+            }
+            Console.WriteLine(count + " " + (fetch_size * processed_size - 10));
+            System.Diagnostics.Debug.Assert(count == fetch_size * processed_size - 10);
+            await res.Close();
+
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("RawDataQuery Passed");
+        }
+        public async Task TestLastDataQuery()
+        {
+            var session_pool = new SessionPool(host, port, pool_size);
+            var status = 0;
+            await session_pool.Open(false);
+            if (debug) session_pool.OpenDebugMode();
+
+            System.Diagnostics.Debug.Assert(session_pool.IsOpen());
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+
+            var device_id = string.Format("{0}.{1}", test_group_name, test_device);
+            var measurements = new List<string> { test_measurements[0], test_measurements[1] };
+            var data_type_lst = new List<TSDataType> { TSDataType.BOOLEAN, TSDataType.FLOAT };
+            var encoding_lst = new List<TSEncoding> { TSEncoding.PLAIN, TSEncoding.PLAIN };
+            var compressor_lst = new List<Compressor> { Compressor.SNAPPY, Compressor.SNAPPY };
+            status = await session_pool.CreateAlignedTimeseriesAsync(device_id, measurements, data_type_lst, encoding_lst, compressor_lst);
+
+            var records = new List<RowRecord>();
+            var values = new List<object>() { true, 20.0f };
+            var device_id_lst = new List<string>() { };
+            for (int i = 1; i <= fetch_size * processed_size; i++)
+            {
+                var record = new RowRecord(i, values, measurements);
+                records.Add(record);
+                device_id_lst.Add(device_id);
+            }
+            status = await session_pool.InsertAlignedRecordsAsync(device_id_lst, records);
+            System.Diagnostics.Debug.Assert(status == 0);
+
+            var paths = new List<string>() { string.Format("{0}.{1}", device_id, test_measurements[0]), string.Format("{0}.{1}", device_id, test_measurements[1]) };
+
+            var res = await session_pool.ExecuteLastDataQueryAsync(paths, fetch_size * processed_size - 10);
+            var count = 0;
+            while (res.HasNext())
+            {
+                var record = res.Next();
+                Console.WriteLine(record);
+                count++;
+            }
+            Console.WriteLine(count + " " + (fetch_size * processed_size - 10));
+            System.Diagnostics.Debug.Assert(count == 2);
+            await res.Close();
+
+            status = await session_pool.DeleteStorageGroupAsync(test_group_name);
+            System.Diagnostics.Debug.Assert(status == 0);
+            await session_pool.Close();
+            Console.WriteLine("LastDataQuery Passed");
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB.Data/Apache.IoTDB.Data.csproj b/src/Apache.IoTDB.Data/Apache.IoTDB.Data.csproj
new file mode 100644
index 0000000..7880ff5
--- /dev/null
+++ b/src/Apache.IoTDB.Data/Apache.IoTDB.Data.csproj
@@ -0,0 +1,29 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+	<PropertyGroup>
+		<AssemblyName>Apache.IoTDB.Data</AssemblyName>
+		<RootNamespace>$(AssemblyName)</RootNamespace>
+		<PackageId>Apache.IoTDB.Data</PackageId>
+        <PackageVersion>1.0.0.3</PackageVersion>
+        <Authors>eedalong, lausannel, MysticBoy, Aiemu</Authors>
+        <Company>LiuLin Lab</Company>
+		<Description>
+			IoTDB implementation of the System.Data.Common provider model.
+			Commonly Used Types:
+			Apache.IoTDB.Data.IoTDBCommand
+			Apache.IoTDB.Data.IoTDBConnection
+			Apache.IoTDB.Data.IoTDBConnectionStringBuilder
+			Apache.IoTDB.Data.IoTDBDataReader
+			Apache.IoTDB.Data.IoTDBException
+			Apache.IoTDB.Data.IoTDBFactory
+			Apache.IoTDB.Data.IoTDBParameter
+			Apache.IoTDB.Data.IoTDBTransaction
+		</Description>
+		<TargetFrameworks>net5.0;net6.0;netstandard2.1;netstandard2.0;net461</TargetFrameworks>
+		<LangVersion>10</LangVersion>
+		<PackageReleaseNotes>Apache.IoTDB.Data是一个IoTDB的ADO.Net 提供器。这将允许你通过.Net访问IoTDB数据库。</PackageReleaseNotes>
+	</PropertyGroup>
+	<ItemGroup>
+		<ProjectReference Include="..\Apache.IoTDB\Apache.IoTDB.csproj" />
+	</ItemGroup>
+</Project>
diff --git a/src/Apache.IoTDB.Data/DataReaderExtensions.cs b/src/Apache.IoTDB.Data/DataReaderExtensions.cs
new file mode 100644
index 0000000..91cd9cf
--- /dev/null
+++ b/src/Apache.IoTDB.Data/DataReaderExtensions.cs
@@ -0,0 +1,85 @@
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Data;
+using System.Data.Common;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Apache.IoTDB.Data
+{
+    public static class DataReaderExtensions
+    {
+        public static SessionPool CreateSession(this IoTDBConnectionStringBuilder db)
+        {
+            return new SessionPool(db.DataSource, db.Port, db.Username, db.Password, db.FetchSize, db.ZoneId, db.PoolSize,db.Compression,db.TimeOut);
+        }
+
+        public static List<T> ToObject<T>(this IDataReader dataReader)
+        {
+            List<T> jArray = new List<T>();
+            try
+            {
+                var t = typeof(T);
+                var pots = t.GetProperties();
+                while (dataReader.Read())
+                {
+                    T jObject = Activator.CreateInstance<T>();
+                    for (int i = 0; i < dataReader.FieldCount; i++)
+                    {
+                        try
+                        {
+                            string strKey = dataReader.GetName(i);
+                            if (dataReader[i] != DBNull.Value)
+                            {
+                                var pr = from p in pots where (p.Name == strKey || p.ColumnNameIs(strKey)) && p.CanWrite select p;
+                                if (pr.Any())
+                                {
+                                    var pi = pr.FirstOrDefault();
+                                    pi.SetValue(jObject, Convert.ChangeType(dataReader[i], pi.PropertyType));
+                                }
+                            }
+                        }
+                        catch (Exception)
+                        {
+
+                        }
+                    }
+                    jArray.Add(jObject);
+                }
+            }
+            catch (Exception ex)
+            {
+                IoTDBException.ThrowExceptionForRC(-10002, $"ToObject<{nameof(T)}>  Error", ex);
+            }
+            return jArray;
+        }
+
+        internal static bool ColumnNameIs(this System.Reflection.PropertyInfo p, string strKey)
+        {
+            return (p.IsDefined(typeof(ColumnAttribute), true) && (p.GetCustomAttributes(typeof(ColumnAttribute), true) as ColumnAttribute[])?.FirstOrDefault().Name == strKey);
+        }
+
+
+        public static DataTable ToDataTable(this IDataReader reader)
+        {
+            var dt = new DataTable();
+            try
+            {
+
+                dt.Load(reader, LoadOption.OverwriteChanges, (object sender, FillErrorEventArgs e) =>
+                {
+
+                });
+            }
+            catch (Exception)
+            {
+
+
+            }
+            return dt;
+        }
+    }
+}
diff --git a/src/Apache.IoTDB.Data/IoTDBCommand.cs b/src/Apache.IoTDB.Data/IoTDBCommand.cs
new file mode 100644
index 0000000..c349ded
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBCommand.cs
@@ -0,0 +1,547 @@
+
+
+using Apache.IoTDB.DataStructure;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Data.Common;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+ 
+
+namespace Apache.IoTDB.Data
+{
+    /// <summary>
+    ///     Represents a SQL statement to be executed against a IoTDB database.
+    /// </summary>
+    public class IoTDBCommand : DbCommand
+    {
+        private readonly Lazy<IoTDBParameterCollection> _parameters = new Lazy<IoTDBParameterCollection>(
+            () => new IoTDBParameterCollection());
+        private IoTDBConnection _connection;
+        private string _commandText;
+        private SessionPool _IoTDB => _connection._IoTDB;
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBCommand" /> class.
+        /// </summary>
+        public IoTDBCommand()
+        {
+
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBCommand" /> class.
+        /// </summary>
+        /// <param name="commandText">The SQL to execute against the database.</param>
+        public IoTDBCommand(string commandText)
+            => CommandText = commandText;
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBCommand" /> class.
+        /// </summary>
+        /// <param name="commandText">The SQL to execute against the database.</param>
+        /// <param name="connection">The connection used by the command.</param>
+        public IoTDBCommand(string commandText, IoTDBConnection connection)
+            : this(commandText)
+        {
+            Connection = connection;
+            CommandTimeout = connection.DefaultTimeout;
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBCommand" /> class.
+        /// </summary>
+        /// <param name="commandText">The SQL to execute against the database.</param>
+        /// <param name="connection">The connection used by the command.</param>
+        /// <param name="transaction">The transaction within which the command executes.</param>
+        public IoTDBCommand(string commandText, IoTDBConnection connection, IoTDBTransaction transaction)
+            : this(commandText, connection)
+            => Transaction = transaction;
+
+        /// <summary>
+        ///     Gets or sets a value indicating how <see cref="CommandText" /> is interpreted. Only
+        ///     <see cref="CommandType.Text" /> is supported.
+        /// </summary>
+        /// <value>A value indicating how <see cref="CommandText" /> is interpreted.</value>
+        public override CommandType CommandType
+        {
+            get => CommandType.Text;
+            set
+            {
+                if (value != CommandType.Text)
+                {
+                    throw new ArgumentException($"Invalid CommandType{value}");
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Gets or sets the SQL to execute against the database.
+        /// </summary>
+        /// <value>The SQL to execute against the database.</value>
+        public override string CommandText
+        {
+            get => _commandText;
+            set
+            {
+                if (DataReader != null)
+                {
+                    throw new InvalidOperationException($"SetRequiresNoOpenReader{nameof(CommandText)}");
+                }
+
+                if (value != _commandText)
+                {
+                    _commandText = value;
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Gets or sets the connection used by the command.
+        /// </summary>
+        /// <value>The connection used by the command.</value>
+        public new virtual IoTDBConnection Connection
+        {
+            get => _connection;
+            set
+            {
+                if (DataReader != null)
+                {
+                    throw new InvalidOperationException($"SetRequiresNoOpenReader{nameof(Connection)}");
+                }
+
+                if (value != _connection)
+                {
+
+                    _connection?.RemoveCommand(this);
+                    _connection = value;
+                    value?.AddCommand(this);
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Gets or sets the connection used by the command. Must be a <see cref="IoTDBConnection" />.
+        /// </summary>
+        /// <value>The connection used by the command.</value>
+        protected override DbConnection DbConnection
+        {
+            get => Connection;
+            set => Connection = (IoTDBConnection)value;
+        }
+
+        /// <summary>
+        ///     Gets or sets the transaction within which the command executes.
+        /// </summary>
+        /// <value>The transaction within which the command executes.</value>
+        public new virtual IoTDBTransaction Transaction { get; set; }
+
+        /// <summary>
+        ///     Gets or sets the transaction within which the command executes. Must be a <see cref="IoTDBTransaction" />.
+        /// </summary>
+        /// <value>The transaction within which the command executes.</value>
+        protected override DbTransaction DbTransaction
+        {
+            get => Transaction;
+            set => Transaction = (IoTDBTransaction)value;
+        }
+
+        /// <summary>
+        ///     Gets the collection of parameters used by the command.
+        /// </summary>
+        /// <value>The collection of parameters used by the command.</value>
+        public new virtual IoTDBParameterCollection Parameters
+            => _parameters.Value;
+
+        /// <summary>
+        ///     Gets the collection of parameters used by the command.
+        /// </summary>
+        /// <value>The collection of parameters used by the command.</value>
+        protected override DbParameterCollection DbParameterCollection
+            => Parameters;
+
+        /// <summary>
+        ///     Gets or sets the number of seconds to wait before terminating the attempt to execute the command. Defaults to 30.
+        /// </summary>
+        /// <value>The number of seconds to wait before terminating the attempt to execute the command.</value>
+        /// <remarks>
+        ///     The timeout is used when the command is waiting to obtain a lock on the table.
+        /// </remarks>
+        public override int CommandTimeout { get; set; } = 30;
+
+        /// <summary>
+        ///     Gets or sets a value indicating whether the command should be visible in an interface control.
+        /// </summary>
+        /// <value>A value indicating whether the command should be visible in an interface control.</value>
+        public override bool DesignTimeVisible { get; set; }
+
+        /// <summary>
+        ///     Gets or sets a value indicating how the results are applied to the row being updated.
+        /// </summary>
+        /// <value>A value indicating how the results are applied to the row being updated.</value>
+        public override UpdateRowSource UpdatedRowSource { get; set; }
+
+        /// <summary>
+        ///     Gets or sets the data reader currently being used by the command, or null if none.
+        /// </summary>
+        /// <value>The data reader currently being used by the command.</value>
+        protected internal virtual IoTDBDataReader DataReader { get; set; }
+
+        /// <summary>
+        ///     Releases any resources used by the connection and closes it.
+        /// </summary>
+        /// <param name="disposing">
+        ///     true to release managed and unmanaged resources; false to release only unmanaged resources.
+        /// </param>
+        protected override void Dispose(bool disposing)
+        {
+
+            base.Dispose(disposing);
+        }
+
+        /// <summary>
+        ///     Creates a new parameter.
+        /// </summary>
+        /// <returns>The new parameter.</returns>
+        public new virtual IoTDBParameter CreateParameter()
+            => new IoTDBParameter();
+
+        /// <summary>
+        ///     Creates a new parameter.
+        /// </summary>
+        /// <returns>The new parameter.</returns>
+        protected override DbParameter CreateDbParameter()
+            => CreateParameter();
+
+        /// <summary>
+        ///     Creates a prepared version of the command on the database.
+        /// </summary>
+        public override void Prepare()
+        {
+            if (_connection?.State != ConnectionState.Open)
+            {
+                throw new InvalidOperationException($"CallRequiresOpenConnection{nameof(Prepare)}");
+            }
+
+            if (string.IsNullOrEmpty(_commandText))
+            {
+                throw new InvalidOperationException($"CallRequiresSetCommandText{nameof(Prepare)}");
+            }
+
+        }
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> against the database and returns a data reader.
+        /// </summary>
+        /// <returns>The data reader.</returns>
+        /// <exception cref="IoTDBException">A IoTDB error occurs during execution.</exception>
+        public new virtual IoTDBDataReader ExecuteReader()
+            => ExecuteReader(CommandBehavior.Default);
+
+
+  
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> against the database and returns a data reader.
+        /// </summary>
+        /// <param name="behavior">
+        ///     A description of the results of the query and its effect on the database.
+        ///     <para>
+        ///         Only <see cref="CommandBehavior.Default" />, <see cref="CommandBehavior.SequentialAccess" />,
+        ///         <see cref="CommandBehavior.SingleResult" />, <see cref="CommandBehavior.SingleRow" />, and
+        ///         <see cref="CommandBehavior.CloseConnection" /> are supported.
+        ///     </para>
+        /// </param>
+        /// <returns>The data reader.</returns>
+        /// <exception cref="IoTDBException">A IoTDB error occurs during execution.</exception>
+        public new virtual IoTDBDataReader ExecuteReader(CommandBehavior behavior)
+        {
+            if ((behavior & ~(CommandBehavior.Default | CommandBehavior.SequentialAccess | CommandBehavior.SingleResult
+                              | CommandBehavior.SingleRow | CommandBehavior.CloseConnection)) != 0)
+            {
+                throw new ArgumentException($"InvalidCommandBehavior{behavior}");
+            }
+
+            if (DataReader != null)
+            {
+                throw new InvalidOperationException($"DataReaderOpen");
+            }
+
+            if (_connection?.State != ConnectionState.Open)
+            {
+                _connection.Open();
+                if (_connection?.State != ConnectionState.Open)
+                {
+                    throw new InvalidOperationException($"CallRequiresOpenConnection{nameof(ExecuteReader)}");
+                }
+            }
+         
+
+            if (string.IsNullOrEmpty(_commandText))
+            {
+                throw new InvalidOperationException($"CallRequiresSetCommandText{nameof(ExecuteReader)}");
+            }
+
+            var unprepared = false;
+            IoTDBDataReader dataReader = null;
+            var closeConnection = (behavior & CommandBehavior.CloseConnection) != 0;
+            try
+            {
+#if DEBUG
+                Debug.WriteLine($"_commandText:{_commandText}");
+#endif
+                int _affectRows = 0;
+                SessionDataSet dataSet=null;
+                bool isok = false;
+                Task<SessionDataSet> taskDataSet = null;
+                if (_parameters.IsValueCreated)
+                {
+
+                    var pms = _parameters.Value;
+                    var record = BindParamters(pms);
+                    throw new NotSupportedException();
+                }
+                else
+                {
+                    
+                    var sessionData = Task.Run(() => _IoTDB.ExecuteQueryStatementAsync(_commandText));
+                    isok = sessionData.Wait(TimeSpan.FromSeconds(CommandTimeout));
+                    if (isok)
+                    {
+                        dataSet = sessionData.Result;
+                        _affectRows = dataSet.FetchSize;
+                    }
+                }
+
+                if (isok && dataSet != null  )
+                {
+                    dataReader = new IoTDBDataReader(this, dataSet, closeConnection  );
+                }
+                else if (taskDataSet.Status == TaskStatus.Running || !isok)
+                {
+                    IoTDBException.ThrowExceptionForRC(-10006, "Execute sql command timeout", null);
+                }
+                else if (taskDataSet.IsCanceled)
+                {
+                    IoTDBException.ThrowExceptionForRC(-10003, "Command is Canceled", null);
+                }
+                else if (taskDataSet.IsFaulted)
+                {
+                    IoTDBException.ThrowExceptionForRC(-10004, taskDataSet.Exception.Message, taskDataSet.Exception?.InnerException);
+                }
+                else
+                {
+                    IoTDBException.ThrowExceptionForRC(_commandText, new IoTDBErrorResult() { Code = -10007, Error = $"Unknow Exception" });
+                }
+            }
+            catch when (unprepared)
+            {
+                throw;
+            }
+            return dataReader;
+        }
+
+        private RowRecord BindParamters(IoTDBParameterCollection pms)
+        {
+            var measures = new List<string>();
+            var values = new List<object> ();
+           
+
+            for (int i = 0; i < pms.Count; i++)
+            {
+
+                var tp = pms[i];
+                measures.Add(tp.ParameterName);
+             //   _commandText = _commandText.Replace(tp.ParameterName, "?");
+                switch (TypeInfo.GetTypeCode(tp.Value?.GetType()))
+                {
+                    case TypeCode.Boolean:
+                       values.Add ((tp.Value as bool?).GetValueOrDefault());
+                        break;
+                    case TypeCode.Char:
+                        values.Add(tp.Value as string);
+                        break;
+                    case TypeCode.Byte:
+                    case TypeCode.SByte:
+                        values.Add((tp.Value as byte?).GetValueOrDefault());
+                        break;
+                    case TypeCode.DateTime:
+                        var t0 = tp.Value as DateTime?;
+                        if (!t0.HasValue)
+                        {
+                            throw new ArgumentException($"InvalidArgumentOfDateTime{tp.Value}");
+                        }
+                        values.Add(t0.GetValueOrDefault());
+                        break;
+                    case TypeCode.DBNull:
+                   
+                        break;
+                    case TypeCode.Single:
+                        values.Add((tp.Value as float?).GetValueOrDefault());
+                        break;
+                    case TypeCode.Decimal:
+                    case TypeCode.Double:
+                        values.Add((tp.Value as double?).GetValueOrDefault());
+                        break;
+                    case TypeCode.Int16:
+                        values.Add((tp.Value as short?).GetValueOrDefault());
+                        break;
+                    case TypeCode.Int32:
+                        values.Add((tp.Value as int?).GetValueOrDefault());
+                        break;
+                    case TypeCode.Int64:
+                        values.Add((tp.Value as long?).GetValueOrDefault());
+                        break;
+                    case TypeCode.UInt16:
+                        values.Add((tp.Value as short?).GetValueOrDefault());
+                        break;
+                    case TypeCode.UInt32:
+                        values.Add((tp.Value as uint?).GetValueOrDefault());
+                        break;
+                    case TypeCode.UInt64:
+                        values.Add((tp.Value as ulong?).GetValueOrDefault());
+                        break;
+                    case TypeCode.String:
+                    default:
+                        values.Add(tp.Value as string);
+                        break;
+                }
+            }
+
+            return   new RowRecord(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),values,measures);
+        }
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> against the database and returns a data reader.
+        /// </summary>
+        /// <param name="behavior">A description of query's results and its effect on the database.</param>
+        /// <returns>The data reader.</returns>
+        protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
+            => ExecuteReader(behavior);
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
+        /// </summary>
+        /// <returns>A task representing the asynchronous operation.</returns>
+        /// <remarks>
+        ///     IoTDB does not support asynchronous execution. Use write-ahead logging instead.
+        /// </remarks>
+        /// <seealso href="http://IoTDB.org/wal.html">Write-Ahead Logging</seealso>
+        public new virtual Task<IoTDBDataReader> ExecuteReaderAsync()
+            => ExecuteReaderAsync(CommandBehavior.Default, CancellationToken.None);
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
+        /// </summary>
+        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
+        /// <returns>A task representing the asynchronous operation.</returns>
+        /// <remarks>
+        ///     IoTDB does not support asynchronous execution. Use write-ahead logging instead.
+        /// </remarks>
+        /// <seealso href="http://IoTDB.org/wal.html">Write-Ahead Logging</seealso>
+        public new virtual Task<IoTDBDataReader> ExecuteReaderAsync(CancellationToken cancellationToken)
+            => ExecuteReaderAsync(CommandBehavior.Default, cancellationToken);
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
+        /// </summary>
+        /// <param name="behavior">A description of query's results and its effect on the database.</param>
+        /// <returns>A task representing the asynchronous operation.</returns>
+        /// <remarks>
+        ///     IoTDB does not support asynchronous execution. Use write-ahead logging instead.
+        /// </remarks>
+        /// <seealso href="http://IoTDB.org/wal.html">Write-Ahead Logging</seealso>
+        public new virtual Task<IoTDBDataReader> ExecuteReaderAsync(CommandBehavior behavior)
+            => ExecuteReaderAsync(behavior, CancellationToken.None);
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
+        /// </summary>
+        /// <param name="behavior">A description of query's results and its effect on the database.</param>
+        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
+        /// <returns>A task representing the asynchronous operation.</returns>
+        /// <remarks>
+        ///     IoTDB does not support asynchronous execution. Use write-ahead logging instead.
+        /// </remarks>
+        /// <seealso href="http://IoTDB.org/wal.html">Write-Ahead Logging</seealso>
+        public new virtual Task<IoTDBDataReader> ExecuteReaderAsync(
+            CommandBehavior behavior,
+            CancellationToken cancellationToken)
+        {
+            cancellationToken.ThrowIfCancellationRequested();
+
+            return Task.FromResult(ExecuteReader(behavior));
+        }
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
+        /// </summary>
+        /// <param name="behavior">A description of query's results and its effect on the database.</param>
+        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
+        /// <returns>A task representing the asynchronous operation.</returns>
+        protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(
+            CommandBehavior behavior,
+            CancellationToken cancellationToken)
+            => await ExecuteReaderAsync(behavior, cancellationToken);
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> against the database.
+        /// </summary>
+        /// <returns>The number of rows inserted, updated, or deleted. -1 for SELECT statements.</returns>
+        /// <exception cref="IoTDBException">A IoTDB error occurs during execution.</exception>
+        public override int ExecuteNonQuery()
+        {
+            if (_connection?.State != ConnectionState.Open)
+            {
+                throw new InvalidOperationException($"CallRequiresOpenConnection{nameof(ExecuteNonQuery)}");
+            }
+            if (_commandText == null)
+            {
+                throw new InvalidOperationException($"CallRequiresSetCommandText{nameof(ExecuteNonQuery)}");
+            }
+            var result = Task.Run(() => _IoTDB.ExecuteNonQueryStatementAsync(_commandText));
+             var ok = result.Wait(TimeSpan.FromSeconds(CommandTimeout));
+            if (!ok) throw new  TimeoutException();
+            return result.Result;
+        }
+
+        /// <summary>
+        ///     Executes the <see cref="CommandText" /> against the database and returns the result.
+        /// </summary>
+        /// <returns>The first column of the first row of the results, or null if no results.</returns>
+        /// <exception cref="IoTDBException">A IoTDB error occurs during execution.</exception>
+        public override object ExecuteScalar()
+        {
+            if (_connection?.State != ConnectionState.Open)
+            {
+                throw new InvalidOperationException($"CallRequiresOpenConnection{nameof(ExecuteScalar)}");
+            }
+            if (_commandText == null)
+            {
+                throw new InvalidOperationException($"CallRequiresSetCommandText{nameof(ExecuteScalar)}");
+            }
+
+            using (var reader = ExecuteReader())
+            {
+                return reader.Read()
+                    ? reader.GetValue(0)
+                    : null;
+            }
+        }
+      
+        /// <summary>
+        ///     Attempts to cancel the execution of the command. Does nothing.
+        /// </summary>
+        public override void Cancel()
+        {
+        }
+
+      
+    }
+}
diff --git a/src/Apache.IoTDB.Data/IoTDBConnection.cs b/src/Apache.IoTDB.Data/IoTDBConnection.cs
new file mode 100644
index 0000000..897c873
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBConnection.cs
@@ -0,0 +1,353 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Common;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+ 
+using System.Linq;
+using System.Threading.Tasks;
+using System.Threading;
+
+namespace Apache.IoTDB.Data
+{
+    /// <summary>
+    ///     Represents a connection to a IoTDB database.
+    /// </summary>
+    public partial class IoTDBConnection : DbConnection
+    {
+ 
+
+        private readonly IList<WeakReference<IoTDBCommand>> _commands = new List<WeakReference<IoTDBCommand>>();
+
+        private string _connectionString;
+        private ConnectionState _state;
+        internal SessionPool  _IoTDB;
+      
+ 
+     
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBConnection" /> class.
+        /// </summary>
+        public IoTDBConnection()
+        {
+            _IoTDB = (ConnectionStringBuilder ?? new IoTDBConnectionStringBuilder()).CreateSession();
+        }
+        public SessionPool SessionPool => _IoTDB;
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBConnection" /> class.
+        /// </summary>
+        /// <param name="connectionString">The string used to open the connection.</param>
+        /// <seealso cref="IoTDBConnectionStringBuilder" />
+        public IoTDBConnection(string connectionString) : this()
+        {
+            ConnectionStringBuilder = new IoTDBConnectionStringBuilder(connectionString);
+            ConnectionString = connectionString;
+        }
+
+
+
+        /// <summary>
+        ///     Gets or sets a string used to open the connection.
+        /// </summary>
+        /// <value>A string used to open the connection.</value>
+        /// <seealso cref="IoTDBConnectionStringBuilder" />
+        public override string ConnectionString
+        {
+            get => _connectionString;
+            set
+            {
+                _connectionString = value;
+                ConnectionStringBuilder = new IoTDBConnectionStringBuilder(value);
+                _IoTDB = ConnectionStringBuilder.CreateSession();
+            }
+        }
+
+        internal IoTDBConnectionStringBuilder ConnectionStringBuilder { get; set; }
+
+
+        /// <summary>
+        ///     Gets the path to the database file. Will be absolute for open connections.
+        /// </summary>
+        /// <value>The path to the database file.</value>
+        public override string DataSource
+        {
+            get
+            {
+                string dataSource = null;
+
+                return dataSource ?? ConnectionStringBuilder.DataSource;
+            }
+        }
+
+        /// <summary>
+        ///     Gets or sets the default <see cref="IoTDBCommand.CommandTimeout"/> value for commands created using
+        ///     this connection. This is also used for internal commands in methods like
+        ///     <see cref="BeginTransaction()"/>.
+        /// </summary>
+        /// <value>The default <see cref="IoTDBCommand.CommandTimeout"/> value</value>
+        public virtual int DefaultTimeout { get; set; } = 60;
+
+
+   
+        /// <summary>
+        ///     Gets the version of IoTDB used by the connection.
+        /// </summary>
+        /// <value>The version of IoTDB used by the connection.</value>
+        public override string ServerVersion
+        {
+            get
+            {
+                throw new NotImplementedException();
+            }
+        }
+        public   string ClientVersion
+        {
+            get
+            {
+
+                throw new NotImplementedException();
+            }
+        }
+        /// <summary>
+        ///     Gets the current state of the connection.
+        /// </summary>
+        /// <value>The current state of the connection.</value>
+        public override ConnectionState State
+            => _state;
+
+        /// <summary>
+        ///     Gets the <see cref="DbProviderFactory" /> for this connection.
+        /// </summary>
+        /// <value>The <see cref="DbProviderFactory" />.</value>
+        protected override DbProviderFactory DbProviderFactory
+            => IoTDBFactory.Instance;
+
+        /// <summary>
+        ///     Gets or sets the transaction currently being used by the connection, or null if none.
+        /// </summary>
+        /// <value>The transaction currently being used by the connection.</value>
+        protected internal virtual IoTDBTransaction Transaction { get; set; }
+
+ 
+
+
+
+
+        private void SetState(ConnectionState value)
+        {
+            var originalState = _state;
+            if (originalState != value)
+            {
+                _state = value;
+                OnStateChange(new StateChangeEventArgs(originalState, value));
+            }
+        }
+
+        /// <summary>
+        ///     Opens a connection to the database using the value of <see cref="ConnectionString" />. If
+        ///     <c>Mode=ReadWriteCreate</c> is used (the default) the file is created, if it doesn't already exist.
+        /// </summary>
+        /// <exception cref="IoTDBException">A IoTDB error occurs while opening the connection.</exception>
+        public override void Open()
+        {
+            OpenAsync().GetAwaiter().GetResult();
+        }
+        public   override   async Task OpenAsync(CancellationToken cancellationToken=default)
+        {
+         
+            if (State == ConnectionState.Open)
+            {
+                return;
+            }
+            if (ConnectionString == null)
+            {
+                throw new InvalidOperationException("Open Requires Set ConnectionString");
+            }
+
+            await _IoTDB.Open(ConnectionStringBuilder.Compression, cancellationToken);
+           if (!_IoTDB.IsOpen())
+            {
+                IoTDBException.ThrowExceptionForRC(-1, "Can't open IoTDB server.");
+            }
+            else
+            {
+                SetState(ConnectionState.Open);
+            }
+        }
+
+        /// <summary>
+        ///     Closes the connection to the database. Open transactions are rolled back.
+        /// </summary>
+        public override void Close()
+        {
+            CloseAsync().GetAwaiter().GetResult(); ;
+        }
+#if NET461_OR_GREATER || NETSTANDARD2_0
+        public  async Task CloseAsync()
+#else
+        public override async Task CloseAsync()
+#endif
+        { 
+            if (State != ConnectionState.Closed)
+                await  _IoTDB.Close();
+            Transaction?.Dispose();
+            _nowdatabase = string.Empty;
+            foreach (var reference in _commands)
+            {
+                if (reference.TryGetTarget(out var command))
+                {
+                    command.Dispose();
+                }
+            }
+            _commands.Clear();
+            SetState(ConnectionState.Closed);
+        }
+
+        /// <summary>
+        ///     Releases any resources used by the connection and closes it.
+        /// </summary>
+        /// <param name="disposing">
+        ///     true to release managed and unmanaged resources; false to release only unmanaged resources.
+        /// </param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Close();
+            }
+            base.Dispose(disposing);
+        }
+
+        /// <summary>
+        ///     Creates a new command associated with the connection.
+        /// </summary>
+        /// <returns>The new command.</returns>
+        /// <remarks>
+        ///     The command's <seealso cref="IoTDBCommand.Transaction" /> property will also be set to the current
+        ///     transaction.
+        /// </remarks>
+        public new virtual IoTDBCommand CreateCommand()
+            => new IoTDBCommand { Connection = this, CommandTimeout = DefaultTimeout, Transaction = Transaction };
+        public virtual IoTDBCommand CreateCommand(string commandtext)
+          => new IoTDBCommand { Connection = this, CommandText = commandtext, CommandTimeout = DefaultTimeout, Transaction = Transaction };
+
+        /// <summary>
+        ///     Creates a new command associated with the connection.
+        /// </summary>
+        /// <returns>The new command.</returns>
+        protected override DbCommand CreateDbCommand()
+            => CreateCommand();
+
+        internal void AddCommand(IoTDBCommand command)
+            => _commands.Add(new WeakReference<IoTDBCommand>(command));
+
+        internal void RemoveCommand(IoTDBCommand command)
+        {
+            for (var i = _commands.Count - 1; i >= 0; i--)
+            {
+                if (!_commands[i].TryGetTarget(out var item)
+                    || item == command)
+                {
+                    _commands.RemoveAt(i);
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Create custom collation.
+        /// </summary>
+        /// <param name="name">Name of the collation.</param>
+        /// <param name="comparison">Method that compares two strings.</param>
+        public virtual void CreateCollation(string name, Comparison<string> comparison)
+            => CreateCollation(name, null, comparison != null ? (_, s1, s2) => comparison(s1, s2) : (Func<object, string, string, int>)null);
+
+        /// <summary>
+        ///     Create custom collation.
+        /// </summary>
+        /// <typeparam name="T">The type of the state object.</typeparam>
+        /// <param name="name">Name of the collation.</param>
+        /// <param name="state">State object passed to each invocation of the collation.</param>
+        /// <param name="comparison">Method that compares two strings, using additional state.</param>
+        public virtual void CreateCollation<T>(string name, T state, Func<T, string, string, int> comparison)
+        {
+            if (string.IsNullOrEmpty(name))
+            {
+                throw new ArgumentNullException(nameof(name));
+            }
+
+            if (State != ConnectionState.Open)
+            {
+                throw new InvalidOperationException($"CallRequiresOpenConnection{nameof(CreateCollation)}");
+            }
+
+
+        }
+
+        /// <summary>
+        ///     Begins a transaction on the connection.
+        /// </summary>
+        /// <returns>The transaction.</returns>
+        public new virtual IoTDBTransaction BeginTransaction()
+            => BeginTransaction(IsolationLevel.Unspecified);
+
+        /// <summary>
+        ///     Begins a transaction on the connection.
+        /// </summary>
+        /// <param name="isolationLevel">The isolation level of the transaction.</param>
+        /// <returns>The transaction.</returns>
+        protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
+            => BeginTransaction(isolationLevel);
+
+        /// <summary>
+        ///     Begins a transaction on the connection.
+        /// </summary>
+        /// <param name="isolationLevel">The isolation level of the transaction.</param>
+        /// <returns>The transaction.</returns>
+        public new virtual IoTDBTransaction BeginTransaction(IsolationLevel isolationLevel)
+        {
+            if (State != ConnectionState.Open)
+            {
+                throw new InvalidOperationException($"CallRequiresOpenConnection{nameof(BeginTransaction)}");
+            }
+            if (Transaction != null)
+            {
+                throw new InvalidOperationException($"ParallelTransactionsNotSupported");
+            }
+
+            return Transaction = new IoTDBTransaction(this, isolationLevel);
+        }
+        internal string _nowdatabase = string.Empty;
+
+        internal bool SelectedDataBase => _nowdatabase != string.Empty ;
+
+        public override string Database => throw new  NotSupportedException();
+
+        /// <summary>
+        ///     Changes the current database.  
+        /// </summary>
+        /// <param name="databaseName">The name of the database to use.</param>
+        /// <exception cref="PlatformNotSupportedException"></exception>
+        public override void ChangeDatabase(string databaseName)
+        {
+            throw new NotSupportedException();
+        }
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="databaseName"></param>
+        /// <returns></returns>
+        /// <exception cref="NotSupportedException"></exception>
+        public bool DatabaseExists(string databaseName)
+        {
+            throw new NotSupportedException();
+        }
+        
+     
+    }
+}
diff --git a/src/Apache.IoTDB.Data/IoTDBConnectionStringBuilder.cs b/src/Apache.IoTDB.Data/IoTDBConnectionStringBuilder.cs
new file mode 100644
index 0000000..1c665bd
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBConnectionStringBuilder.cs
@@ -0,0 +1,408 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data.Common;
+using System.Diagnostics;
+using System.Globalization;
+using System.Reflection;
+using System.Threading;
+
+namespace Apache.IoTDB.Data
+{
+    /// <summary>
+    ///     Provides a simple way to create and manage the contents of connection strings used by
+    ///     <see cref="IoTDBConnection" />.
+    /// </summary>
+    public class IoTDBConnectionStringBuilder : DbConnectionStringBuilder
+    {
+        private const string DataSourceKeyword = "DataSource";
+        private const string UserNameKeyword = "Username";
+        private const string PasswordKeyword = "Password";
+        private const string PortKeyword = "Port";
+        private const string FetchSizeKeyword = "FetchSize";
+        private const string CompressionKeyword = "Compression";
+        private const string PoolSizeKeyword = "PoolSize";
+        private const string ZoneIdKeyword = "ZoneId";
+        private const string TimeOutKeyword = "TimeOut";
+
+        private enum Keywords
+        {
+            DataSource,
+            Username,
+            Password,
+            Port,
+            FetchSize,
+            Compression,
+            PoolSize,
+            ZoneId,
+            TimeOut
+        }
+
+        private static readonly IReadOnlyList<string> _validKeywords;
+        private static readonly IReadOnlyDictionary<string, Keywords> _keywords;
+
+        private string _dataSource = "127.0.0.1";
+        private string _userName = "root";
+        private string _password = "root";
+        private bool _enableRpcCompression = false;
+        private int  _fetchSize = 1800;
+        private string _zoneId = "UTC+08:00";
+        private int  _port = 6667;
+      private   int  _poolSize =8;
+        private int _timeOut=10000;
+
+        static IoTDBConnectionStringBuilder()
+        {
+            var validKeywords = new string[9];
+            validKeywords[(int)Keywords.DataSource] = DataSourceKeyword;
+             validKeywords[(int)Keywords.Username] = UserNameKeyword;
+            validKeywords[(int)Keywords.Password] = PasswordKeyword;
+            validKeywords[(int)Keywords.Port] = PortKeyword;
+            validKeywords[(int)Keywords.FetchSize] = FetchSizeKeyword;
+            validKeywords[(int)Keywords.Compression] = CompressionKeyword;
+            validKeywords[(int)Keywords.PoolSize] = PoolSizeKeyword;
+            validKeywords[(int)Keywords.ZoneId] = ZoneIdKeyword;
+            validKeywords[(int)Keywords.TimeOut] =TimeOutKeyword;
+            _validKeywords = validKeywords;
+
+            _keywords = new Dictionary<string, Keywords>(9, StringComparer.OrdinalIgnoreCase)
+            {
+                [DataSourceKeyword] = Keywords.DataSource,
+                [UserNameKeyword] = Keywords.Username,
+                [PasswordKeyword] = Keywords.Password,
+                [PortKeyword] = Keywords.Port,
+                [FetchSizeKeyword] = Keywords.FetchSize,
+                [CompressionKeyword] = Keywords.Compression,
+                [PoolSizeKeyword] = Keywords.PoolSize,
+                [ZoneIdKeyword] = Keywords.ZoneId,
+                [TimeOutKeyword] = Keywords.TimeOut
+            };
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBConnectionStringBuilder" /> class.
+        /// </summary>
+        public IoTDBConnectionStringBuilder()
+        {
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBConnectionStringBuilder" /> class.
+        /// </summary>
+        /// <param name="connectionString">
+        ///     The initial connection string the builder will represent. Can be null.
+        /// </param>
+        public IoTDBConnectionStringBuilder(string connectionString)
+            => ConnectionString = connectionString;
+
+        /// <summary>
+        ///     Gets or sets the database file.
+        /// </summary>
+        /// <value>The database file.</value>
+        public virtual string DataSource
+        {
+            get => _dataSource;
+            set => base[DataSourceKeyword] = _dataSource = value;
+        }
+        public virtual string Username
+        {
+            get => _userName;
+            set => base[UserNameKeyword] = _userName = value;
+        }
+  
+        public virtual string Password
+        {
+            get => _password;
+            set => base[PasswordKeyword] = _password = value;
+        }
+        public virtual int  Port
+        {
+            get => _port;
+            set => base[PortKeyword] = _port = value;
+        }
+
+        public virtual int FetchSize
+        {
+            get => _fetchSize;
+            set => base[FetchSizeKeyword] = _fetchSize = value;
+        }
+        public virtual bool Compression
+        {
+            get => _enableRpcCompression;
+            set => base[CompressionKeyword] = _enableRpcCompression = value;
+        }
+        public virtual int PoolSize
+        {
+            get => _poolSize;
+            set => base[PoolSizeKeyword] = _poolSize = value;
+        }
+        public virtual string ZoneId
+        {
+            get => _zoneId;
+            set => base[ZoneIdKeyword] = _zoneId = value;
+        }
+
+        public virtual int TimeOut
+    {
+            get => _timeOut;
+            set => base[PoolSizeKeyword] = _timeOut = value;
+        }
+
+        /// <summary>
+        ///     Gets a collection containing the keys used by the connection string.
+        /// </summary>
+        /// <value>A collection containing the keys used by the connection string.</value>
+        public override ICollection Keys
+            => new ReadOnlyCollection<string>((string[])_validKeywords);
+
+        /// <summary>
+        ///     Gets a collection containing the values used by the connection string.
+        /// </summary>
+        /// <value>A collection containing the values used by the connection string.</value>
+        public override ICollection Values
+        {
+            get
+            {
+                var values = new object[_validKeywords.Count];
+                for (var i = 0; i < _validKeywords.Count; i++)
+                {
+                    values[i] = GetAt((Keywords)i);
+                }
+
+                return new ReadOnlyCollection<object>(values);
+            }
+        }
+
+
+
+
+
+
+
+        /// <summary>
+        ///     Gets or sets the value associated with the specified key.
+        /// </summary>
+        /// <param name="keyword">The key.</param>
+        /// <returns>The value.</returns>
+        public override object this[string keyword]
+        {
+            get => GetAt(GetIndex(keyword));
+            set
+            {
+                if (value == null)
+                {
+                    Remove(keyword);
+
+                    return;
+                }
+           
+                switch (GetIndex(keyword))
+                {
+                    case Keywords.DataSource:
+                        DataSource = Convert.ToString(value, CultureInfo.InvariantCulture);
+                        return;
+                    case Keywords.Username:
+                        Username= Convert.ToString(value, CultureInfo.InvariantCulture);
+                        return;
+                    case Keywords.Password:
+                        Password = Convert.ToString(value, CultureInfo.InvariantCulture);
+                        return;
+      
+                    case Keywords.Port:
+                        Port = Convert.ToInt32(value, CultureInfo.InvariantCulture);
+                        return;
+                    case Keywords.FetchSize:
+                        FetchSize = Convert.ToInt32(value, CultureInfo.InvariantCulture);
+                        return;
+                    case Keywords.Compression:
+                        Compression = Convert.ToBoolean(value, CultureInfo.InvariantCulture);
+                        return;
+                    case Keywords.PoolSize:
+                        PoolSize = Convert.ToInt32(value, CultureInfo.InvariantCulture);
+                        return;
+                    case Keywords.ZoneId:
+                        ZoneId = Convert.ToString(value, CultureInfo.InvariantCulture);
+                        return;
+                    case Keywords.TimeOut:
+                        TimeOut = Convert.ToInt32(value, CultureInfo.InvariantCulture);
+                        return;
+                    default:
+                        Debug.WriteLine(false, "Unexpected keyword: " + keyword);
+                        return;
+                }
+            }
+        }
+
+        private static TEnum ConvertToEnum<TEnum>(object value)
+            where TEnum : struct
+        {
+            if (value is string stringValue)
+            {
+                return (TEnum)Enum.Parse(typeof(TEnum), stringValue, ignoreCase: true);
+            }
+
+            if (value is TEnum enumValue)
+            {
+                enumValue = (TEnum)value;
+            }
+            else if (value.GetType().GetTypeInfo().IsEnum)
+            {
+                throw new ArgumentException($"ConvertFailed{value.GetType()},{typeof(TEnum)}");
+            }
+            else
+            {
+                enumValue = (TEnum)Enum.ToObject(typeof(TEnum), value);
+            }
+
+            if (!Enum.IsDefined(typeof(TEnum), enumValue))
+            {
+                throw new ArgumentOutOfRangeException(
+                    nameof(value),
+                    value,
+                    $"Invalid Enum Value{typeof(TEnum)},{enumValue}");
+            }
+
+            return enumValue;
+        }
+
+        /// <summary>
+        ///     Clears the contents of the builder.
+        /// </summary>
+        public override void Clear()
+        {
+            base.Clear();
+
+            for (var i = 0; i < _validKeywords.Count; i++)
+            {
+                Reset((Keywords)i);
+            }
+        }
+
+        /// <summary>
+        ///     Determines whether the specified key is used by the connection string.
+        /// </summary>
+        /// <param name="keyword">The key to look for.</param>
+        /// <returns>true if it is use; otherwise, false.</returns>
+        public override bool ContainsKey(string keyword)
+            => _keywords.ContainsKey(keyword);
+
+        /// <summary>
+        ///     Removes the specified key and its value from the connection string.
+        /// </summary>
+        /// <param name="keyword">The key to remove.</param>
+        /// <returns>true if the key was used; otherwise, false.</returns>
+        public override bool Remove(string keyword)
+        {
+            if (!_keywords.TryGetValue(keyword, out var index)
+                || !base.Remove(_validKeywords[(int)index]))
+            {
+                return false;
+            }
+
+            Reset(index);
+
+            return true;
+        }
+
+        /// <summary>
+        ///     Determines whether the specified key should be serialized into the connection string.
+        /// </summary>
+        /// <param name="keyword">The key to check.</param>
+        /// <returns>true if it should be serialized; otherwise, false.</returns>
+        public override bool ShouldSerialize(string keyword)
+            => _keywords.TryGetValue(keyword, out var index) && base.ShouldSerialize(_validKeywords[(int)index]);
+
+        /// <summary>
+        ///     Gets the value of the specified key if it is used.
+        /// </summary>
+        /// <param name="keyword">The key.</param>
+        /// <param name="value">The value.</param>
+        /// <returns>true if the key was used; otherwise, false.</returns>
+        public override bool TryGetValue(string keyword, out object value)
+        {
+            if (!_keywords.TryGetValue(keyword, out var index))
+            {
+                value = null;
+
+                return false;
+            }
+
+            value = GetAt(index);
+
+            return true;
+        }
+
+        private object GetAt(Keywords index)
+        {
+  
+            switch (index)
+            {
+                case Keywords.DataSource:
+                    return DataSource;
+                case Keywords.Password:
+                    return Password;
+                case Keywords.Username:
+                    return Username;
+    
+                case Keywords.Port:
+                    return Port;
+                case Keywords.FetchSize:
+                    return FetchSize;
+                case Keywords.Compression:
+                    return Compression;
+                case Keywords.PoolSize:
+                    return PoolSize;
+                case Keywords.ZoneId:
+                    return ZoneId;
+                case Keywords.TimeOut:
+                    return TimeOut;
+                default:
+                    Debug.Assert(false, "Unexpected keyword: " + index);
+                    return null;
+            }
+        }
+
+        private static Keywords GetIndex(string keyword)
+            => !_keywords.TryGetValue(keyword, out var index)
+                ? throw new ArgumentException($"Keyword Not Supported{keyword}")
+                : index;
+
+        private void Reset(Keywords index)
+        {
+            switch (index)
+            {
+                case Keywords.DataSource:
+                    _dataSource = "127.0.0.1";
+                    return;
+                case Keywords.Password:
+                    _password = "root";
+                    return;
+                case Keywords.Username:
+                    _userName = "root";
+                    return;
+                case Keywords.Port:
+                    _port=6667;
+                    return;
+                case Keywords.FetchSize:
+                    _fetchSize = 1800;
+                    return;
+                case Keywords.Compression:
+                    _enableRpcCompression = false;
+                    return;
+                case Keywords.PoolSize:
+                    _poolSize = 8;
+                    return;
+                case Keywords.ZoneId:
+                    _zoneId = "UTC+08:00";
+                    return;
+                case Keywords.TimeOut:
+                    _timeOut = 10000;//10sec.
+                    return;
+                default:
+                    Debug.Assert(false, "Unexpected keyword: " + index);
+                    return;
+            }
+        }
+    }
+}
diff --git a/src/Apache.IoTDB.Data/IoTDBDataReader.cs b/src/Apache.IoTDB.Data/IoTDBDataReader.cs
new file mode 100644
index 0000000..71d2abd
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBDataReader.cs
@@ -0,0 +1,548 @@
+using Apache.IoTDB.DataStructure;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Common;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+ 
+
+namespace Apache.IoTDB.Data
+{
+    /// <summary>
+    ///     Provides methods for reading the result of a command executed against a IoTDB database.
+    /// </summary>
+    public class IoTDBDataReader : DbDataReader
+    {
+        private readonly SessionPool _IoTDB;
+        private readonly IoTDBCommand _command;
+        private bool _hasRows;
+        private readonly int _recordsAffected;
+        private bool _closed;
+        private readonly  List<string> _metas;
+        private bool _closeConnection;
+ 
+        private int _fieldCount;
+      
+        RowRecord rowdata= null;
+
+
+        SessionDataSet _dataSet;
+        internal IoTDBDataReader(IoTDBCommand IoTDBCommand, SessionDataSet dataSet, bool closeConnection)
+        {
+            _IoTDB = IoTDBCommand.Connection._IoTDB;
+            _command = IoTDBCommand;
+            _closeConnection = closeConnection;
+            _fieldCount = dataSet.ColumnNames.Count;
+            _hasRows = dataSet.RowCount > 0;
+            _recordsAffected =dataSet.RowCount;
+            _closed = _closeConnection;
+            _metas = dataSet.ColumnNames;
+            _dataSet = dataSet;
+        }
+
+        /// <summary>
+        ///     Gets the depth of nesting for the current row. Always zero.
+        /// </summary>
+        /// <value>The depth of nesting for the current row.</value>
+        public override int Depth => 0;
+
+        /// <summary>
+        ///     Gets the number of columns in the current row.
+        /// </summary>
+        /// <value>The number of columns in the current row.</value>
+        public override int FieldCount => _fieldCount+1;
+
+        /// <summary>
+        ///     Gets a value indicating whether the data reader contains any rows.
+        /// </summary>
+        /// <value>A value indicating whether the data reader contains any rows.</value>
+        public override bool HasRows
+            => _hasRows;
+ 
+ 
+        /// <summary>
+        ///     Gets a value indicating whether the data reader is closed.
+        /// </summary>
+        /// <value>A value indicating whether the data reader is closed.</value>
+        public override bool IsClosed
+            => _closed;
+
+        /// <summary>
+        ///     Gets the number of rows inserted, updated, or deleted. -1 for SELECT statements.
+        /// </summary>
+        /// <value>The number of rows inserted, updated, or deleted.</value>
+        public override int RecordsAffected
+        {
+            get
+            {
+                return _recordsAffected; 
+            }
+        }
+
+        /// <summary>
+        ///     Gets the value of the specified column.
+        /// </summary>
+        /// <param name="name">The name of the column. The value is case-sensitive.</param>
+        /// <returns>The value.</returns>
+        public override object this[string name]
+            => this[GetOrdinal(name)];
+
+        /// <summary>
+        ///     Gets the value of the specified column.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value.</returns>
+        public override object this[int ordinal]
+            => GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets an enumerator that can be used to iterate through the rows in the data reader.
+        /// </summary>
+        /// <returns>The enumerator.</returns>
+        public override IEnumerator GetEnumerator()
+            => new DbEnumerator(this, closeReader: false);
+
+
+        /// <summary>
+        ///     Advances to the next row in the result set.
+        /// </summary>
+        /// <returns>true if there are more rows; otherwise, false.</returns>
+        public override bool Read()
+        {
+            if (_closed)
+            {
+                throw new InvalidOperationException($"DataReaderClosed{nameof(Read)}");
+            }
+            if (_dataSet.HasNext())
+            {
+                rowdata = _dataSet.Next();
+            }
+            else
+            {
+                rowdata = null;
+            }
+            return rowdata != null;
+
+        }
+
+        /// <summary>
+        ///     Advances to the next result set for batched statements.
+        /// </summary>
+        /// <returns>true if there are more result sets; otherwise, false.</returns>
+        public override bool NextResult()
+        {
+            return Read();
+        }
+
+        /// <summary>
+        ///     Closes the data reader.
+        /// </summary>
+        public override void Close()
+            => Dispose(true);
+
+        /// <summary>
+        ///     Releases any resources used by the data reader and closes it.
+        /// </summary>
+        /// <param name="disposing">
+        ///     true to release managed and unmanaged resources; false to release only unmanaged resources.
+        /// </param>
+        protected override void Dispose(bool disposing)
+        {
+            if (!disposing)
+            {
+                return;
+            }
+            _dataSet.Close().GetAwaiter().GetResult();
+            _command.DataReader = null;
+
+            if (_closeConnection  )
+            {
+                _command.Connection.Close();
+                _closed = true;
+            }
+            rowdata = null;
+        
+        }
+
+        /// <summary>
+        ///     Gets the name of the specified column.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The name of the column.</returns>
+        public override string GetName(int ordinal)
+        {
+            return ordinal==0? "timestamp" : rowdata.Measurements[ordinal-1];
+        }
+
+        /// <summary>
+        ///     Gets the ordinal of the specified column.
+        /// </summary>
+        /// <param name="name">The name of the column.</param>
+        /// <returns>The zero-based column ordinal.</returns>
+        public override int GetOrdinal(string name)
+            => "timestamp"==name?0: rowdata.Measurements.IndexOf(  name)+1;
+
+        public override string GetDataTypeName(int ordinal)
+        {
+            return GetFieldType(ordinal).Name;
+        }
+
+        /// <summary>
+        ///     Gets the data type of the specified column.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The data type of the column.</returns>
+        public override Type GetFieldType(int ordinal)
+        {
+        
+            return ordinal==0?typeof(DateTime): rowdata.GetCrlType(ordinal-1);
+        }
+
+        /// <summary>
+        ///     Gets a value indicating whether the specified column is <see cref="DBNull" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>true if the specified column is <see cref="DBNull" />; otherwise, false.</returns>
+        public override bool IsDBNull(int ordinal)
+                => GetValue(ordinal) == DBNull.Value;
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="bool" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override bool GetBoolean(int ordinal) => GetFieldValue<bool>(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="byte" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override byte GetByte(int ordinal) => GetFieldValue<byte>(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="char" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override char GetChar(int ordinal) => GetFieldValue<char>(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="DateTime" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override DateTime GetDateTime(int ordinal)
+        {
+            return GetFieldValue<DateTime>(ordinal);
+        }
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="DateTimeOffset" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public virtual DateTimeOffset GetDateTimeOffset(int ordinal)
+        {
+            return GetDateTime(ordinal);
+        }
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="TimeSpan" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public virtual TimeSpan GetTimeSpan(int ordinal)
+        {
+            var val = GetInt64(ordinal);
+            return TimeSpan.FromMilliseconds(val);
+        }
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="decimal" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override decimal GetDecimal(int ordinal) => (decimal)GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="double" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override double GetDouble(int ordinal) => (double)GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="float" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override float GetFloat(int ordinal) => (float)GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="Guid" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override Guid GetGuid(int ordinal) => GetFieldValue<Guid>(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="short" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override short GetInt16(int ordinal) => (short)GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="ushort" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public ushort GetUInt16(int ordinal) => (ushort)GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="int" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override int GetInt32(int ordinal) => (int)GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="uint" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public uint GetUInt32(int ordinal) => (uint)GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="long" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override long GetInt64(int ordinal) => (long)GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="ulong" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public ulong GetUInt64(int ordinal) => (ulong)GetValue(ordinal);
+
+        /// <summary>
+        ///     Gets the value of the specified column as a <see cref="string" />.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override string GetString(int ordinal) => (string)GetValue(ordinal);
+ 
+  
+        /// <summary>
+        ///     Reads a stream of bytes from the specified column. Not supported.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <param name="dataOffset">The index from which to begin the read operation.</param>
+        /// <param name="buffer">The buffer into which the data is copied.</param>
+        /// <param name="bufferOffset">The index to which the data will be copied.</param>
+        /// <param name="length">The maximum number of bytes to read.</param>
+        /// <returns>The actual number of bytes read.</returns>
+        public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
+        {
+            throw new NotSupportedException();
+        }
+
+        /// <summary>
+        ///     Reads a stream of characters from the specified column. Not supported.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <param name="dataOffset">The index from which to begin the read operation.</param>
+        /// <param name="buffer">The buffer into which the data is copied.</param>
+        /// <param name="bufferOffset">The index to which the data will be copied.</param>
+        /// <param name="length">The maximum number of characters to read.</param>
+        /// <returns>The actual number of characters read.</returns>
+        public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)
+           => throw new NotSupportedException();
+
+        /// <summary>
+        /// Retrieves data as a Stream.  Not supported.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The returned object.</returns>
+        public override Stream GetStream(int ordinal)
+         => throw new NotSupportedException();
+        /// <summary>
+        ///     Gets the value of the specified column.
+        /// </summary>
+        /// <typeparam name="T">The type of the value.</typeparam>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override T GetFieldValue<T>(int ordinal) => (T)Convert.ChangeType(GetValue(ordinal), typeof(T));
+
+        /// <summary>
+        ///     Gets the value of the specified column.
+        /// </summary>
+        /// <param name="ordinal">The zero-based column ordinal.</param>
+        /// <returns>The value of the column.</returns>
+        public override object GetValue(int ordinal)
+        {
+            object result;
+            if (ordinal == 0)
+            {
+                result = rowdata.GetDateTime();
+            }
+            else
+            {
+                result = rowdata.Values[ordinal - 1];
+            }
+            if (result == null)
+
+            {
+                result = DBNull.Value;
+            }
+            return result;
+        }
+
+       
+
+        /// <summary>
+        ///     Gets the column values of the current row.
+        /// </summary>
+        /// <param name="values">An array into which the values are copied.</param>
+        /// <returns>The number of values copied into the array.</returns>
+        public override int GetValues(object[] values)
+        {
+            int count = 0;
+            values[0] = rowdata.GetDateTime();
+            for (int i = 0; i < _fieldCount; i++)
+            {
+                var obj = rowdata.Values[i];
+                if (obj != null  )
+                {
+                    values[i+1] = obj;
+                    count++;
+                }
+            }
+            return count;
+        }
+
+
+        /// <summary>
+        ///     Returns a System.Data.DataTable that describes the column metadata of the System.Data.Common.DbDataReader.
+        /// </summary>
+        /// <returns>A System.Data.DataTable that describes the column metadata.</returns>
+        public override DataTable GetSchemaTable()
+        {
+            if (_dataSet.HasNext())
+            {
+                rowdata = _dataSet.GetRow();
+            }
+                   var schemaTable = new DataTable("SchemaTable");
+            if (_metas != null && rowdata !=null)
+            {
+                var ColumnName = new DataColumn(SchemaTableColumn.ColumnName, typeof(string));
+                var ColumnOrdinal = new DataColumn(SchemaTableColumn.ColumnOrdinal, typeof(int));
+                var ColumnSize = new DataColumn(SchemaTableColumn.ColumnSize, typeof(int));
+                var NumericPrecision = new DataColumn(SchemaTableColumn.NumericPrecision, typeof(short));
+                var NumericScale = new DataColumn(SchemaTableColumn.NumericScale, typeof(short));
+
+                var DataType = new DataColumn(SchemaTableColumn.DataType, typeof(Type));
+                var DataTypeName = new DataColumn("DataTypeName", typeof(string));
+
+                var IsLong = new DataColumn(SchemaTableColumn.IsLong, typeof(bool));
+                var AllowDBNull = new DataColumn(SchemaTableColumn.AllowDBNull, typeof(bool));
+
+                var IsUnique = new DataColumn(SchemaTableColumn.IsUnique, typeof(bool));
+                var IsKey = new DataColumn(SchemaTableColumn.IsKey, typeof(bool));
+                var IsAutoIncrement = new DataColumn(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool));
+
+                var BaseCatalogName = new DataColumn(SchemaTableOptionalColumn.BaseCatalogName, typeof(string));
+                var BaseSchemaName = new DataColumn(SchemaTableColumn.BaseSchemaName, typeof(string));
+                var BaseTableName = new DataColumn(SchemaTableColumn.BaseTableName, typeof(string));
+                var BaseColumnName = new DataColumn(SchemaTableColumn.BaseColumnName, typeof(string));
+
+                var BaseServerName = new DataColumn(SchemaTableOptionalColumn.BaseServerName, typeof(string));
+                var IsAliased = new DataColumn(SchemaTableColumn.IsAliased, typeof(bool));
+                var IsExpression = new DataColumn(SchemaTableColumn.IsExpression, typeof(bool));
+
+                var columns = schemaTable.Columns;
+
+                columns.Add(ColumnName);
+                columns.Add(ColumnOrdinal);
+                columns.Add(ColumnSize);
+                columns.Add(NumericPrecision);
+                columns.Add(NumericScale);
+                columns.Add(IsUnique);
+                columns.Add(IsKey);
+                columns.Add(BaseServerName);
+                columns.Add(BaseCatalogName);
+                columns.Add(BaseColumnName);
+                columns.Add(BaseSchemaName);
+                columns.Add(BaseTableName);
+                columns.Add(DataType);
+                columns.Add(DataTypeName);
+                columns.Add(AllowDBNull);
+                columns.Add(IsAliased);
+                columns.Add(IsExpression);
+                columns.Add(IsAutoIncrement);
+                columns.Add(IsLong);
+
+
+
+                var schemaRow1 = schemaTable.NewRow();
+
+                var columnName1 = "timestamp";
+                schemaRow1[ColumnName] = columnName1;
+                schemaRow1[ColumnOrdinal] = 0;
+
+                schemaRow1[NumericPrecision] = DBNull.Value;
+                schemaRow1[NumericScale] = DBNull.Value;
+                schemaRow1[BaseServerName] = _command.Connection.DataSource;
+
+                schemaRow1[BaseColumnName] = columnName1;
+                schemaRow1[BaseSchemaName] = DBNull.Value;
+                var tableName1 = string.Empty;
+                schemaRow1[BaseTableName] = tableName1;
+                schemaRow1[DataType] = typeof(DateTime);
+                schemaRow1[DataTypeName] = typeof(DateTime).Name;
+                schemaRow1[IsExpression] = columnName1 == null;
+                schemaRow1[IsLong] = DBNull.Value;
+                schemaRow1[IsKey] = true;
+        
+ 
+                schemaTable.Rows.Add(schemaRow1);
+
+
+                for (var i = 1; i < rowdata.Measurements.Count+1; i++)
+                {
+                    var schemaRow = schemaTable.NewRow();
+
+                    var columnName = rowdata.Measurements[i-1] ;
+                    schemaRow[ColumnName] = columnName;
+                    schemaRow[ColumnOrdinal] = i;
+               
+                    schemaRow[NumericPrecision] = DBNull.Value;
+                    schemaRow[NumericScale] = DBNull.Value;
+                    schemaRow[BaseServerName] = _command.Connection.DataSource;
+              
+                    schemaRow[BaseColumnName] = columnName;
+                    schemaRow[BaseSchemaName] = DBNull.Value;
+                    var tableName = string.Empty;
+                    schemaRow[BaseTableName] = tableName;
+                    schemaRow[DataType] = GetFieldType(i);
+                    schemaRow[DataTypeName] = GetDataTypeName(i);
+                    schemaRow[IsExpression] = columnName == null;
+                    schemaRow[IsLong] = DBNull.Value;
+                    schemaRow[IsKey]= false;
+                    schemaRow[AllowDBNull] = true;
+                    schemaTable.Rows.Add(schemaRow);
+                }
+
+            }
+
+            return schemaTable;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB.Data/IoTDBException.cs b/src/Apache.IoTDB.Data/IoTDBException.cs
new file mode 100644
index 0000000..6dc848a
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBException.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Data.Common;
+ 
+
+namespace Apache.IoTDB.Data
+{
+    /// <summary>
+    ///     Represents a IoTDB error.
+    /// </summary>
+    public class IoTDBException : DbException
+    {
+        IoTDBErrorResult _IoTDBError;
+
+        public IoTDBException(IoTDBErrorResult IoTDBError) : base(IoTDBError.Error, null)
+        {
+            _IoTDBError = IoTDBError;
+            base.HResult = _IoTDBError.Code;
+        }
+
+        public IoTDBException(IoTDBErrorResult IoTDBError, Exception ex) : base(IoTDBError.Error, ex)
+        {
+            _IoTDBError = IoTDBError;
+            base.HResult = _IoTDBError.Code;
+        }
+
+
+   
+
+      
+        public override string Message => _IoTDBError?.Error;
+        public override int ErrorCode =>   (int) _IoTDBError?.Code;
+        /// <summary>
+        ///     Throws an exception with a specific IoTDB error code value.
+        /// </summary>
+        /// <param name="rc">The IoTDB error code corresponding to the desired exception.</param>
+        /// <param name="db">A handle to database connection.</param>
+        /// <remarks>
+        ///     No exception is thrown for non-error result codes.
+        /// </remarks>
+        public static void ThrowExceptionForRC(string _commandText, IoTDBErrorResult IoTDBError)
+        {
+            var te = new IoTDBException(IoTDBError);
+            te.Data.Add("commandText", _commandText);
+            throw te;
+        }
+        public static void ThrowExceptionForRC( IoTDBErrorResult IoTDBError)
+        {
+            var te = new IoTDBException(IoTDBError);
+            throw te;
+        }
+        public static void ThrowExceptionForRC(IntPtr _IoTDB)
+        {
+            var te = new IoTDBException(new IoTDBErrorResult() {   });
+            throw te;
+        }
+        public static void ThrowExceptionForRC(int code, string message, Exception ex)
+        {
+            var te = new IoTDBException(new IoTDBErrorResult() { Code = code, Error = message }, ex);
+            throw te;
+        }
+        public static void ThrowExceptionForRC(int code, string message)
+        {
+            var te = new IoTDBException(new IoTDBErrorResult() { Code = code, Error = message });
+            throw te;
+        }
+    }
+}
diff --git a/src/Apache.IoTDB.Data/IoTDBFactory.cs b/src/Apache.IoTDB.Data/IoTDBFactory.cs
new file mode 100644
index 0000000..58a9dd0
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBFactory.cs
@@ -0,0 +1,47 @@
+using System.Data.Common;
+
+namespace Apache.IoTDB.Data
+{
+    /// <summary>
+    ///     Creates instances of various Maikebing.Data.IoTDB classes.
+    /// </summary>
+    public class IoTDBFactory : DbProviderFactory
+    {
+        private IoTDBFactory()
+        {
+        }
+
+        /// <summary>
+        ///     The singleton instance.
+        /// </summary>
+        public static readonly IoTDBFactory Instance = new IoTDBFactory();
+
+        /// <summary>
+        ///     Creates a new command.
+        /// </summary>
+        /// <returns>The new command.</returns>
+        public override DbCommand CreateCommand()
+            => new IoTDBCommand();
+
+        /// <summary>
+        ///     Creates a new connection.
+        /// </summary>
+        /// <returns>The new connection.</returns>
+        public override DbConnection CreateConnection()
+            => new IoTDBConnection();
+
+        /// <summary>
+        ///     Creates a new connection string builder.
+        /// </summary>
+        /// <returns>The new connection string builder.</returns>
+        public override DbConnectionStringBuilder CreateConnectionStringBuilder()
+            => new IoTDBConnectionStringBuilder();
+
+        /// <summary>
+        ///     Creates a new parameter.
+        /// </summary>
+        /// <returns>The new parameter.</returns>
+        public override DbParameter CreateParameter()
+            => new IoTDBParameter();
+    }
+}
diff --git a/src/Apache.IoTDB.Data/IoTDBParameter.cs b/src/Apache.IoTDB.Data/IoTDBParameter.cs
new file mode 100644
index 0000000..344e1f4
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBParameter.cs
@@ -0,0 +1,207 @@
+ using System;
+using System.Data;
+using System.Data.Common;
+
+namespace Apache.IoTDB.Data
+{
+    // TODO: Truncate to specified size
+    // TODO: Infer type and size from value
+    /// <summary>
+    ///     Represents a parameter and its value in a <see cref="IoTDBCommand" />.
+    /// </summary>
+    /// <remarks>Due to IoTDB's dynamic type system, parameter values are not converted.</remarks>
+    public class IoTDBParameter : DbParameter
+    {
+        private string _parameterName = string.Empty;
+        private object _value;
+        private int? _size;
+        private TSDataType? _IoTDBType;
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBParameter" /> class.
+        /// </summary>
+        public IoTDBParameter()
+        {
+        }
+       
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBParameter" /> class.
+        /// </summary>
+        /// <param name="name">The name of the parameter.</param>
+        /// <param name="value">The value of the parameter. Can be null.</param>
+        public IoTDBParameter(string name, object value)
+        {
+            if (string.IsNullOrEmpty(name))
+            {
+                throw new ArgumentNullException(nameof(name));
+            }
+
+            _parameterName = name;
+            Value = value;
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBParameter" /> class.
+        /// </summary>
+        /// <param name="name">The name of the parameter.</param>
+        /// <param name="type">The type of the parameter.</param>
+        public IoTDBParameter(string name, TSDataType type)
+        {
+            if (string.IsNullOrEmpty(name))
+            {
+                throw new ArgumentNullException(nameof(name));
+            }
+
+            _parameterName = name;
+            IoTDBType = type;
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBParameter" /> class.
+        /// </summary>
+        /// <param name="name">The name of the parameter.</param>
+        /// <param name="type">The type of the parameter.</param>
+        /// <param name="size">The maximum size, in bytes, of the parameter.</param>
+        public IoTDBParameter(string name, TSDataType type, int size)
+            : this(name, type)
+            => Size = size;
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBParameter" /> class.
+        /// </summary>
+        /// <param name="name">The name of the parameter.</param>
+        /// <param name="type">The type of the parameter.</param>
+        /// <param name="size">The maximum size, in bytes, of the parameter.</param>
+        /// <param name="sourceColumn">The source column used for loading the value. Can be null.</param>
+        public IoTDBParameter(string name, TSDataType type, int size, string sourceColumn)
+            : this(name, type, size)
+            => SourceColumn = sourceColumn;
+
+        /// <summary>
+        ///     Gets or sets the type of the parameter.
+        /// </summary>
+        /// <value>The type of the parameter.</value>
+        /// <remarks>Due to IoTDB's dynamic type system, parameter values are not converted.</remarks>
+ 
+        public override DbType DbType { get; set; } = DbType.String;
+
+        /// <summary>
+        ///     Gets or sets the IoTDB type of the parameter.
+        /// </summary>
+        /// <value>The IoTDB type of the parameter.</value>
+        /// <remarks>Due to IoTDB's dynamic type system, parameter values are not converted.</remarks>
+
+        public virtual TSDataType IoTDBType
+        {
+            get => _IoTDBType.GetValueOrDefault();//?? IoTDBValueBinder.GetIoTDBType(_value);
+            set => _IoTDBType = value;
+        }
+
+        /// <summary>
+        ///     Gets or sets the direction of the parameter. Only <see cref="ParameterDirection.Input" /> is supported.
+        /// </summary>
+        /// <value>The direction of the parameter.</value>
+        public override ParameterDirection Direction
+        {
+            get => ParameterDirection.Input;
+            set
+            {
+                if (value != ParameterDirection.Input)
+                {
+                    throw new ArgumentException($"InvalidParameterDirection{value}");
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Gets or sets a value indicating whether the parameter is nullable.
+        /// </summary>
+        /// <value>A value indicating whether the parameter is nullable.</value>
+        public override bool IsNullable { get; set; }
+
+        /// <summary>
+        ///     Gets or sets the name of the parameter.
+        /// </summary>
+        /// <value>The name of the parameter.</value>
+        public override string ParameterName
+        {
+            get => _parameterName;
+            set
+            {
+                if (string.IsNullOrEmpty(value))
+                {
+                    throw new ArgumentNullException(nameof(value));
+                }
+
+                _parameterName = value;
+            }
+        }
+
+        /// <summary>
+        ///     Gets or sets the maximum size, in bytes, of the parameter.
+        /// </summary>
+        /// <value>The maximum size, in bytes, of the parameter.</value>
+        public override int Size
+        {
+            get => _size
+                ?? (_value is string stringValue
+                    ? stringValue.Length
+                    : _value is byte[] byteArray
+                        ? byteArray.Length
+                        : 0);
+
+            set
+            {
+                if (value < -1)
+                {
+                    // NB: Message is provided by the framework
+                    throw new ArgumentOutOfRangeException(nameof(value), value, message: null);
+                }
+
+                _size = value;
+            }
+        }
+
+        /// <summary>
+        ///     Gets or sets the source column used for loading the value.
+        /// </summary>
+        /// <value>The source column used for loading the value.</value>
+        public override string SourceColumn { get; set; } = string.Empty;
+
+        /// <summary>
+        ///     Gets or sets a value indicating whether the source column is nullable.
+        /// </summary>
+        /// <value>A value indicating whether the source column is nullable.</value>
+        public override bool SourceColumnNullMapping { get; set; }
+
+        /// <summary>
+        ///     Gets or sets the value of the parameter.
+        /// </summary>
+        /// <value>The value of the parameter.</value>
+        /// <remarks>Due to IoTDB's dynamic type system, parameter values are not converted.</remarks>
+        public override object Value
+        {
+            get => _value;
+            set { _value = value; }
+        }
+#if NET45
+        public override DataRowVersion SourceVersion { get; set; }
+#endif
+        /// <summary>
+        ///     Resets the <see cref="DbType" /> property to its original value.
+        /// </summary>
+        public override void ResetDbType()
+            => ResetIoTDBType();
+
+        /// <summary>
+        ///     Resets the <see cref="IoTDBType" /> property to its original value.
+        /// </summary>
+        public virtual void ResetIoTDBType()
+        {
+            DbType = DbType.String;
+            IoTDBType = TSDataType.NONE;
+        }
+
+        
+    }
+}
diff --git a/src/Apache.IoTDB.Data/IoTDBParameterCollection.cs b/src/Apache.IoTDB.Data/IoTDBParameterCollection.cs
new file mode 100644
index 0000000..8856967
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBParameterCollection.cs
@@ -0,0 +1,351 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data.Common;
+using System.Linq;
+using System.Reflection;
+
+namespace Apache.IoTDB.Data
+{
+    /// <summary>
+    ///     Represents a collection of IoTDB parameters.
+    /// </summary>
+    public class IoTDBParameterCollection : DbParameterCollection
+    {
+        private readonly List<IoTDBParameter> _parameters = new List<IoTDBParameter>();
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="IoTDBParameterCollection" /> class.
+        /// </summary>
+        protected internal IoTDBParameterCollection()
+        {
+        }
+
+        /// <summary>
+        ///     Gets the number of items in the collection.
+        /// </summary>
+        /// <value>The number of items in the collection.</value>
+        public override int Count
+            => _parameters.Count;
+
+        /// <summary>
+        ///     Gets the object used to synchronize access to the collection.
+        /// </summary>
+        /// <value>The object used to synchronize access to the collection.</value>
+        public override object SyncRoot
+            => ((ICollection)_parameters).SyncRoot;
+
+#if NET45
+        public override bool IsFixedSize => throw null;
+
+        public override bool IsReadOnly => throw null;
+
+        public override bool IsSynchronized => ((ICollection)_parameters).IsSynchronized;
+#endif
+        /// <summary>
+        ///     Gets or sets the parameter at the specified index.
+        /// </summary>
+        /// <param name="index">The zero-based index of the parameter.</param>
+        /// <returns>The parameter.</returns>
+        public new virtual IoTDBParameter this[int index]
+        {
+            get => _parameters[index];
+            set
+            {
+                if (_parameters[index] == value)
+                {
+                    return;
+                }
+
+                _parameters[index] = value;
+            }
+        }
+
+        /// <summary>
+        ///     Gets or sets the parameter with the specified name.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter.</param>
+        /// <returns>The parameter.</returns>
+        public new virtual IoTDBParameter this[string parameterName]
+        {
+            get => this[IndexOfChecked(parameterName)];
+            set => this[IndexOfChecked(parameterName)] = value;
+        }
+
+        /// <summary>
+        ///     Adds a parameter to the collection.
+        /// </summary>
+        /// <param name="value">The parameter to add. Must be a <see cref="IoTDBParameter" />.</param>
+        /// <returns>The zero-based index of the parameter that was added.</returns>
+        public override int Add(object value)
+        {
+            var tpv = (IoTDBParameter)value;
+            _parameters.Add(tpv);
+            return Count - 1;
+        }
+
+        /// <summary>
+        ///     Adds a parameter to the collection.
+        /// </summary>
+        /// <param name="value">The parameter to add.</param>
+        /// <returns>The parameter that was added.</returns>
+        public virtual IoTDBParameter Add(IoTDBParameter value)
+        {
+            _parameters.Add(value);
+
+            return value;
+        }
+
+        /// <summary>
+        ///     Adds a parameter to the collection.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter.</param>
+        /// <param name="type">The IoTDB type of the parameter.</param>
+        /// <returns>The parameter that was added.</returns>
+        public virtual IoTDBParameter Add(string parameterName, TSDataType type)
+            => Add(new IoTDBParameter(parameterName, type));
+
+        /// <summary>
+        ///     Adds a parameter to the collection.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter.</param>
+        /// <param name="type">The IoTDB type of the parameter.</param>
+        /// <param name="size">The maximum size, in bytes, of the parameter.</param>
+        /// <returns>The parameter that was added.</returns>
+        public virtual IoTDBParameter Add(string parameterName, TSDataType type, int size)
+            => Add(new IoTDBParameter(parameterName, type, size));
+
+        /// <summary>
+        ///     Adds a parameter to the collection.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter.</param>
+        /// <param name="type">The IoTDB type of the parameter.</param>
+        /// <param name="size">The maximum size, in bytes, of the parameter.</param>
+        /// <param name="sourceColumn">
+        ///     The source column used for loading the value of the parameter. Can be null.
+        /// </param>
+        /// <returns>The parameter that was added.</returns>
+        public virtual IoTDBParameter Add(string parameterName, TSDataType type, int size, string sourceColumn)
+            => Add(new IoTDBParameter(parameterName, type, size, sourceColumn));
+
+        /// <summary>
+        ///     Adds multiple parameters to the collection.
+        /// </summary>
+        /// <param name="values">
+        ///     An array of parameters to add. They must be <see cref="IoTDBParameter" /> objects.
+        /// </param>
+        public override void AddRange(Array values)
+            => AddRange(values.Cast<IoTDBParameter>());
+
+        /// <summary>
+        ///     Adds multiple parameters to the collection.
+        /// </summary>
+        /// <param name="values">The parameters to add.</param>
+        public virtual void AddRange(IEnumerable<IoTDBParameter> values)
+            => _parameters.AddRange(values);
+
+        /// <summary>
+        ///     Adds a parameter to the collection.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter.</param>
+        /// <param name="value">The value of the parameter. Can be null.</param>
+        /// <returns>The parameter that was added.</returns>
+        public virtual IoTDBParameter AddWithValue(string parameterName, object value)
+        {
+            var parameter = new IoTDBParameter(parameterName, value);
+            Add(parameter);
+
+            return parameter;
+        }
+        /// <summary>
+        ///     Adds a parameter to the collection.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter.</param>
+        /// <param name="value">The value of the parameter. Can be null.</param>
+        /// <returns>The parameter that was added.</returns>
+        public virtual IoTDBParameter AddWithValue( object value)
+        {
+            var parameter = new IoTDBParameter(Guid.NewGuid().ToString(), value);
+            Add(parameter);
+            return parameter;
+        }
+        /// <summary>
+        ///     Removes all parameters from the collection.
+        /// </summary>
+        public override void Clear()
+            => _parameters.Clear();
+
+        /// <summary>
+        ///     Gets a value indicating whether the collection contains the specified parameter.
+        /// </summary>
+        /// <param name="value">The parameter to look for. Must be a <see cref="IoTDBParameter" />.</param>
+        /// <returns>true if the collection contains the parameter; otherwise, false.</returns>
+        public override bool Contains(object value)
+            => Contains((IoTDBParameter)value);
+
+        /// <summary>
+        ///     Gets a value indicating whether the collection contains the specified parameter.
+        /// </summary>
+        /// <param name="value">The parameter to look for.</param>
+        /// <returns>true if the collection contains the parameter; otherwise, false.</returns>
+        public virtual bool Contains(IoTDBParameter value)
+            => _parameters.Contains(value);
+
+        /// <summary>
+        ///     Gets a value indicating whether the collection contains a parameter with the specified name.
+        /// </summary>
+        /// <param name="value">The name of the parameter.</param>
+        /// <returns>true if the collection contains the parameter; otherwise, false.</returns>
+        public override bool Contains(string value)
+            => IndexOf(value) != -1;
+
+        /// <summary>
+        ///     Copies the collection to an array of parameters.
+        /// </summary>
+        /// <param name="array">
+        ///     The array into which the parameters are copied. Must be an array of <see cref="IoTDBParameter" /> objects.
+        /// </param>
+        /// <param name="index">The zero-based index to which the parameters are copied.</param>
+        public override void CopyTo(Array array, int index)
+            => CopyTo((IoTDBParameter[])array, index);
+
+        /// <summary>
+        ///     Copies the collection to an array of parameters.
+        /// </summary>
+        /// <param name="array">The array into which the parameters are copied.</param>
+        /// <param name="index">The zero-based index to which the parameters are copied.</param>
+        public virtual void CopyTo(IoTDBParameter[] array, int index)
+            => _parameters.CopyTo(array, index);
+
+        /// <summary>
+        ///     Gets an enumerator that iterates through the collection.
+        /// </summary>
+        /// <returns>The enumerator.</returns>
+        public override IEnumerator GetEnumerator()
+            => _parameters.GetEnumerator();
+
+        /// <summary>
+        ///     Gets a parameter at the specified index.
+        /// </summary>
+        /// <param name="index">The zero-based index of the parameter.</param>
+        /// <returns>The parameter.</returns>
+        protected override DbParameter GetParameter(int index)
+            => this[index];
+
+        /// <summary>
+        ///     Gets a parameter with the specified name.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter.</param>
+        /// <returns>The parameter.</returns>
+        protected override DbParameter GetParameter(string parameterName)
+            => GetParameter(IndexOfChecked(parameterName));
+
+        /// <summary>
+        ///     Gets the index of the specified parameter.
+        /// </summary>
+        /// <param name="value">The parameter. Must be a <see cref="IoTDBParameter" />.</param>
+        /// <returns>The zero-based index of the parameter.</returns>
+        public override int IndexOf(object value)
+            => IndexOf((IoTDBParameter)value);
+
+        /// <summary>
+        ///     Gets the index of the specified parameter.
+        /// </summary>
+        /// <param name="value">The parameter.</param>
+        /// <returns>The zero-based index of the parameter.</returns>
+        public virtual int IndexOf(IoTDBParameter value)
+            => _parameters.IndexOf(value);
+
+        /// <summary>
+        ///     Gets the index of the parameter with the specified name.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter.</param>
+        /// <returns>The zero-based index of the parameter or -1 if not found.</returns>
+        public override int IndexOf(string parameterName)
+        {
+            for (var index = 0; index < _parameters.Count; index++)
+            {
+                if (_parameters[index].ParameterName == parameterName)
+                {
+                    return index;
+                }
+            }
+
+            return -1;
+        }
+
+        /// <summary>
+        ///     Inserts a parameter into the collection at the specified index.
+        /// </summary>
+        /// <param name="index">The zero-based index at which the parameter should be inserted.</param>
+        /// <param name="value">The parameter to insert. Must be a <see cref="IoTDBParameter" />.</param>
+        public override void Insert(int index, object value)
+            => Insert(index, (IoTDBParameter)value);
+
+        /// <summary>
+        ///     Inserts a parameter into the collection at the specified index.
+        /// </summary>
+        /// <param name="index">The zero-based index at which the parameter should be inserted.</param>
+        /// <param name="value">The parameter to insert.</param>
+        public virtual void Insert(int index, IoTDBParameter value)
+            => _parameters.Insert(index, value);
+
+        /// <summary>
+        ///     Removes a parameter from the collection.
+        /// </summary>
+        /// <param name="value">The parameter to remove. Must be a <see cref="IoTDBParameter" />.</param>
+        public override void Remove(object value)
+            => Remove((IoTDBParameter)value);
+
+        /// <summary>
+        ///     Removes a parameter from the collection.
+        /// </summary>
+        /// <param name="value">The parameter to remove.</param>
+        public virtual void Remove(IoTDBParameter value)
+            => _parameters.Remove(value);
+
+        /// <summary>
+        ///     Removes a parameter from the collection at the specified index.
+        /// </summary>
+        /// <param name="index">The zero-based index of the parameter to remove.</param>
+        public override void RemoveAt(int index)
+            => _parameters.RemoveAt(index);
+
+        /// <summary>
+        ///     Removes a parameter with the specified name from the collection.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter to remove.</param>
+        public override void RemoveAt(string parameterName)
+            => RemoveAt(IndexOfChecked(parameterName));
+
+        /// <summary>
+        ///     Sets the parameter at the specified index.
+        /// </summary>
+        /// <param name="index">The zero-based index of the parameter to set.</param>
+        /// <param name="value">The parameter. Must be a <see cref="IoTDBParameter" />.</param>
+        protected override void SetParameter(int index, DbParameter value)
+            => this[index] = (IoTDBParameter)value;
+
+        /// <summary>
+        ///     Sets the parameter with the specified name.
+        /// </summary>
+        /// <param name="parameterName">The name of the parameter to set.</param>
+        /// <param name="value">The parameter. Must be a <see cref="IoTDBParameter" />.</param>
+        protected override void SetParameter(string parameterName, DbParameter value)
+            => SetParameter(IndexOfChecked(parameterName), value);
+
+      
+
+        private int IndexOfChecked(string parameterName)
+        {
+            var index = IndexOf(parameterName);
+            if (index == -1)
+            {
+                throw new IndexOutOfRangeException($"ParameterNotFound{parameterName}");
+            }
+
+            return index;
+        }
+    }
+}
diff --git a/src/Apache.IoTDB.Data/IoTDBResult.cs b/src/Apache.IoTDB.Data/IoTDBResult.cs
new file mode 100644
index 0000000..5ebc023
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBResult.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Apache.IoTDB.Data
+{
+    public class IoTDBErrorResult
+    {
+ 
+        public int Code  { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public string Error  { get; set; }
+    }
+}
diff --git a/src/Apache.IoTDB.Data/IoTDBTransaction.cs b/src/Apache.IoTDB.Data/IoTDBTransaction.cs
new file mode 100644
index 0000000..27cf963
--- /dev/null
+++ b/src/Apache.IoTDB.Data/IoTDBTransaction.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Data;
+using System.Data.Common;
+
+namespace Apache.IoTDB.Data
+{
+    /// <summary>
+    ///     Represents a transaction made against a IoTDB database.
+    /// </summary>
+    public class IoTDBTransaction : DbTransaction
+    {
+        private IoTDBConnection _connection;
+        private readonly IsolationLevel _isolationLevel;
+        private bool _completed;
+        private bool _externalRollback;
+
+        internal IoTDBTransaction(IoTDBConnection connection, IsolationLevel isolationLevel)
+        {
+            _connection = connection;
+            _isolationLevel = isolationLevel;
+        }
+
+        /// <summary>
+        ///     Gets the connection associated with the transaction.
+        /// </summary>
+        /// <value>The connection associated with the transaction.</value>
+        public new virtual IoTDBConnection Connection
+            => _connection;
+
+        /// <summary>
+        ///     Gets the connection associated with the transaction.
+        /// </summary>
+        /// <value>The connection associated with the transaction.</value>
+        protected override DbConnection DbConnection
+            => Connection;
+
+        internal bool ExternalRollback
+            => _externalRollback;
+
+        /// <summary>
+        ///     Gets the isolation level for the transaction. This cannot be changed if the transaction is completed or
+        ///     closed.
+        /// </summary>
+        /// <value>The isolation level for the transaction.</value>
+        public override IsolationLevel IsolationLevel => IsolationLevel.Unspecified;
+         
+
+        /// <summary>
+        ///     Applies the changes made in the transaction.
+        /// </summary>
+        public override void Commit()
+        {
+            //if (_externalRollback || _completed || _connection.State != ConnectionState.Open)
+            //{
+            //    throw new InvalidOperationException(Resources.TransactionCompleted);
+            //}
+ 
+            //_connection.ExecuteNonQuery("COMMIT;");
+            Complete();
+        }
+
+        /// <summary>
+        ///     Reverts the changes made in the transaction.
+        /// </summary>
+        public override void Rollback()
+        {
+            //if (_completed || _connection.State != ConnectionState.Open)
+            //{
+            //    throw new InvalidOperationException(Resources.TransactionCompleted);
+            //}
+
+            RollbackInternal();
+        }
+
+        /// <summary>
+        ///     Releases any resources used by the transaction and rolls it back.
+        /// </summary>
+        /// <param name="disposing">
+        ///     true to release managed and unmanaged resources; false to release only unmanaged resources.
+        /// </param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing
+                && !_completed
+                && _connection.State == ConnectionState.Open)
+            {
+                RollbackInternal();
+            }
+        }
+
+        private void Complete()
+        {
+            if (_connection!=null)_connection.Transaction = null;
+            _connection = null;
+            _completed = true;
+        }
+
+        private void RollbackInternal()
+        {
+            Complete();
+        }
+
+        private void RollbackExternal(object userData)
+        {
+            _externalRollback = true;
+        }
+    }
+}
diff --git a/src/Apache.IoTDB.Data/Properties/AssemblyInfo.cs b/src/Apache.IoTDB.Data/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8af8797
--- /dev/null
+++ b/src/Apache.IoTDB.Data/Properties/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Text;
+[assembly: InternalsVisibleTo("Apache.IoTDB.Tests")]
diff --git a/src/Apache.IoTDB/Apache.IoTDB.csproj b/src/Apache.IoTDB/Apache.IoTDB.csproj
new file mode 100644
index 0000000..7df5a7a
--- /dev/null
+++ b/src/Apache.IoTDB/Apache.IoTDB.csproj
@@ -0,0 +1,22 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+	<PropertyGroup>
+		<TargetFrameworks>net5.0;net6.0;netstandard2.1;netstandard2.0;net461</TargetFrameworks>
+		<LangVersion>latest</LangVersion>
+        <PackageVersion>1.0.0.3</PackageVersion>
+        <Authors>eedalong, lausannel, Aiemu, MysticBoy</Authors>
+        <Company>LiuLin Lab</Company>
+        <PackageDescription>C# client for Apache IoTDB</PackageDescription>
+        <PackageProjectUrl>https://github.com/eedalong/Apache-IoTDB-Client-CSharp</PackageProjectUrl>
+        <RepositoryUrl>https://github.com/eedalong/Apache-IoTDB-Client-CSharp</RepositoryUrl>
+
+	</PropertyGroup>
+
+	<ItemGroup>
+		<PackageReference Include="ApacheThrift" Version="0.14.1" />
+	</ItemGroup>
+	<ItemGroup Condition="'$(TargetFramework)' == 'net461' or '$(TargetFramework)' == 'netstandard2.0'">
+		<PackageReference Include="IndexRange" Version="1.0.2" />
+	</ItemGroup>
+
+</Project>
diff --git a/src/Apache.IoTDB/Client.cs b/src/Apache.IoTDB/Client.cs
new file mode 100644
index 0000000..0fb5507
--- /dev/null
+++ b/src/Apache.IoTDB/Client.cs
@@ -0,0 +1,20 @@
+using Thrift.Transport;
+
+namespace Apache.IoTDB
+{
+    public class Client
+    {
+        public IClientRPCService.Client ServiceClient { get; }
+        public long SessionId { get; }
+        public long StatementId { get; }
+        public TFramedTransport Transport { get; }
+
+        public Client(IClientRPCService.Client client, long sessionId, long statementId, TFramedTransport transport)
+        {
+            ServiceClient = client;
+            SessionId = sessionId;
+            StatementId = statementId;
+            Transport = transport;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB/ConcurrentClientQueue.cs b/src/Apache.IoTDB/ConcurrentClientQueue.cs
new file mode 100644
index 0000000..32ff3c7
--- /dev/null
+++ b/src/Apache.IoTDB/ConcurrentClientQueue.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+
+namespace Apache.IoTDB
+{
+    public class ConcurrentClientQueue
+    {
+        public ConcurrentQueue<Client> ClientQueue { get; }
+
+        public ConcurrentClientQueue(List<Client> clients)
+        {
+            ClientQueue = new ConcurrentQueue<Client>(clients);
+        }
+        public ConcurrentClientQueue()
+        {
+            ClientQueue = new ConcurrentQueue<Client>();
+        }
+        public void Add(Client client) => Return(client);
+
+        public void Return(Client client)
+        {
+            Monitor.Enter(ClientQueue);
+            ClientQueue.Enqueue(client);
+            Monitor.PulseAll(ClientQueue); // wake up all threads waiting on the queue, refresh the waiting time
+            Monitor.Exit(ClientQueue);
+            Thread.Sleep(0);
+        }
+        int _ref = 0;
+        public void AddRef()
+        {
+            lock (this)
+            {
+                _ref++;
+            }
+        }
+        public int GetRef()
+        {
+            return _ref;
+        }
+        public void RemoveRef()
+        {
+            lock (this)
+            {
+                _ref--;
+            }
+        }
+        public int Timeout { get; set; } = 10;
+        public Client Take()
+        {
+            Client client = null;
+            Monitor.Enter(ClientQueue);
+            while(true){
+                bool timeout = false;
+                if (ClientQueue.IsEmpty)
+                {
+                    timeout = !Monitor.Wait(ClientQueue, TimeSpan.FromSeconds(Timeout));
+                }
+                ClientQueue.TryDequeue(out client);
+
+                if(client != null || timeout){
+                    break;
+                }
+            }
+            Monitor.Exit(ClientQueue);
+            if (client == null)
+            {
+                throw new TimeoutException($"Connection pool is empty and wait time out({Timeout}s)!");
+            }
+            return client;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB/DataStructure/ArrayExtensions.cs b/src/Apache.IoTDB/DataStructure/ArrayExtensions.cs
new file mode 100644
index 0000000..28d4e89
--- /dev/null
+++ b/src/Apache.IoTDB/DataStructure/ArrayExtensions.cs
@@ -0,0 +1,76 @@
+#if NET461_OR_GREATER || NETSTANDARD2_0
+//https://github.com/Grax32/ArrayExtensions/blob/master/docs/index.md
+
+using System;
+namespace Grax32.Extensions
+{
+    public static class ArrayExtensions
+    {
+        public static void Fill<T>(this T[] destinationArray, T value)
+        {
+            if (destinationArray == null)
+            {
+                throw new ArgumentNullException(nameof(destinationArray));
+            }
+
+            destinationArray[0] = value;
+            FillInternal(destinationArray, 1);
+        }
+
+        public static void Fill<T>(this T[] destinationArray, T[] values)
+        {
+            if (destinationArray == null)
+            {
+                throw new ArgumentNullException(nameof(destinationArray));
+            }
+
+            var copyLength = values.Length;
+            var destinationArrayLength = destinationArray.Length;
+
+            if (copyLength == 0)
+            {
+                throw new ArgumentException("Parameter must contain at least one value.", nameof(values));
+            }
+
+            if (copyLength > destinationArrayLength)
+            {
+                // value to copy is longer than destination,
+                // so fill destination with first part of value
+                Array.Copy(values, destinationArray, destinationArrayLength);
+                return;
+            }
+
+            Array.Copy(values, destinationArray, copyLength);
+
+            FillInternal(destinationArray, copyLength);
+        }
+
+        private static void FillInternal<T>(this T[] destinationArray, int copyLength)
+        {
+            var destinationArrayLength = destinationArray.Length;
+            var destinationArrayHalfLength = destinationArrayLength / 2;
+
+            // looping copy from beginning of array to current position
+            // doubling copy length with each pass
+            for (; copyLength < destinationArrayHalfLength; copyLength *= 2)
+            {
+                Array.Copy(
+                    sourceArray: destinationArray,
+                    sourceIndex: 0,
+                    destinationArray: destinationArray,
+                    destinationIndex: copyLength,
+                    length: copyLength);
+            }
+
+            // we're past halfway, meaning only a single copy remains
+            // exactly fill remainder of array
+            Array.Copy(
+                sourceArray: destinationArray,
+                sourceIndex: 0,
+                destinationArray: destinationArray,
+                destinationIndex: copyLength,
+                length: destinationArrayLength - copyLength);
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/src/Apache.IoTDB/DataStructure/BitMap.cs b/src/Apache.IoTDB/DataStructure/BitMap.cs
new file mode 100644
index 0000000..0b792f6
--- /dev/null
+++ b/src/Apache.IoTDB/DataStructure/BitMap.cs
@@ -0,0 +1,130 @@
+using System;
+#if NET461_OR_GREATER || NETSTANDARD2_0
+using Grax32.Extensions;
+#endif
+public class BitMap
+{
+    private static byte[] BIT_UTIL = new byte[] { 1, 2, 4, 8, 16, 32, 64, 255 };
+    private static byte[] UNMARK_BIT_UTIL =
+      new byte[] {
+        (byte) 0XFE, // 11111110
+        (byte) 0XFD, // 11111101
+        (byte) 0XFB, // 11111011
+        (byte) 0XF7, // 11110111
+        (byte) 0XEF, // 11101111
+        (byte) 0XDF, // 11011111
+        (byte) 0XBF, // 10111111
+        (byte) 0X7F // 01111111
+      };
+    private byte[] bits;
+    private int size;
+
+    /** Initialize a BitMap with given size. */
+    public BitMap(int size)
+    {
+        this.size = size;
+        bits = new byte[size / 8 + 1];
+#if NET461_OR_GREATER || NETSTANDARD2_0
+        bits.Fill((byte)0);
+#else
+        Array.Fill<byte>(bits, (byte)0);
+#endif
+    }
+
+    /** Initialize a BitMap with given size and bytes. */
+    public BitMap(int size, byte[] bits)
+    {
+        this.size = size;
+        this.bits = bits;
+    }
+
+    public byte[] getByteArray()
+    {
+        return this.bits;
+    }
+
+    public int getSize()
+    {
+        return this.size;
+    }
+
+    /** returns the value of the bit with the specified index. */
+    public bool isMarked(int position)
+    {
+        return (bits[position / 8] & BIT_UTIL[position % 8]) != 0;
+    }
+
+    /** mark as 1 at all positions. */
+    public void markAll()
+    {
+#if NET461_OR_GREATER || NETSTANDARD2_0
+        bits.Fill((byte)0xFF);
+#else
+        Array.Fill(bits, (byte)0xFF);
+#endif
+
+    }
+
+    /** mark as 1 at the given bit position. */
+    public void mark(int position)
+    {
+        bits[position / 8] |= BIT_UTIL[position % 8];
+    }
+
+    /** mark as 0 at all positions. */
+    public void reset()
+    {
+#if NET461_OR_GREATER || NETSTANDARD2_0
+        bits.Fill((byte)0xFF);
+#else
+        Array.Fill(bits, (byte)0);
+#endif
+    }
+
+    public void unmark(int position)
+    {
+        bits[position / 8] &= UNMARK_BIT_UTIL[position % 8];
+    }
+
+    /** whether all bits are zero, i.e., no Null value */
+    public bool isAllUnmarked()
+    {
+        int j;
+        for (j = 0; j < size / 8; j++)
+        {
+            if (bits[j] != (byte)0)
+            {
+                return false;
+            }
+        }
+        for (j = 0; j < size % 8; j++)
+        {
+            if ((bits[size / 8] & BIT_UTIL[j]) != 0)
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /** whether all bits are one, i.e., all are Null */
+    public bool isAllMarked()
+    {
+        int j;
+        for (j = 0; j < size / 8; j++)
+        {
+            if (bits[j] != (byte)0XFF)
+            {
+                return false;
+            }
+        }
+        for (j = 0; j < size % 8; j++)
+        {
+            if ((bits[size / 8] & BIT_UTIL[j]) == 0)
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB/DataStructure/ByteBuffer.cs b/src/Apache.IoTDB/DataStructure/ByteBuffer.cs
new file mode 100644
index 0000000..fa2eaa1
--- /dev/null
+++ b/src/Apache.IoTDB/DataStructure/ByteBuffer.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Linq;
+using System.Text;
+
+namespace Apache.IoTDB.DataStructure
+{
+    public class ByteBuffer
+    {
+        private byte[] _buffer;
+        private int _writePos;
+        private int _readPos;
+        private int _totalLength;
+        private readonly bool _isLittleEndian = BitConverter.IsLittleEndian;
+
+        public ByteBuffer(byte[] buffer)
+        {
+            _buffer = buffer;
+            _readPos = 0;
+            _writePos = buffer.Length;
+            _totalLength = buffer.Length;
+        }
+
+        public ByteBuffer(int reserve = 1)
+        {
+            _buffer = new byte[reserve];
+            _writePos = 0;
+            _readPos = 0;
+            _totalLength = reserve;
+        }
+
+        public bool HasRemaining()
+        {
+            return _readPos < _writePos;
+        }
+
+        // these for read
+        public byte GetByte()
+        {
+            var byteVal = _buffer[_readPos];
+            _readPos += 1;
+            return byteVal;
+        }
+
+        public bool GetBool()
+        {
+            var boolValue = BitConverter.ToBoolean(_buffer, _readPos);
+            _readPos += 1;
+            return boolValue;
+        }
+
+        public int GetInt()
+        {
+            var intBuff = _buffer[_readPos..(_readPos + 4)];
+            if (_isLittleEndian) intBuff = intBuff.Reverse().ToArray();
+#if NET461_OR_GREATER || NETSTANDARD2_0
+            var intValue = BitConverter.ToInt32(intBuff,0);
+#else
+            var intValue = BitConverter.ToInt32(intBuff);
+#endif
+
+            _readPos += 4;
+            return intValue;
+        }
+
+        public long GetLong()
+        {
+            var longBuff = _buffer[_readPos..(_readPos + 8)];
+
+            if (_isLittleEndian) longBuff = longBuff.Reverse().ToArray();
+#if NET461_OR_GREATER || NETSTANDARD2_0
+            var longValue = BitConverter.ToInt64(longBuff,0);
+#else
+            var longValue = BitConverter.ToInt64(longBuff);
+#endif
+
+            _readPos += 8;
+            return longValue;
+        }
+
+        public float GetFloat()
+        {
+            var floatBuff = _buffer[_readPos..(_readPos + 4)];
+
+            if (_isLittleEndian) floatBuff = floatBuff.Reverse().ToArray();
+#if NET461_OR_GREATER || NETSTANDARD2_0
+            var floatValue = BitConverter.ToSingle(floatBuff,0);
+#else
+            var floatValue = BitConverter.ToSingle(floatBuff);
+#endif
+            _readPos += 4;
+            return floatValue;
+        }
+
+        public double GetDouble()
+        {
+            var doubleBuff = _buffer[_readPos..(_readPos + 8)];
+
+            if (_isLittleEndian) doubleBuff = doubleBuff.Reverse().ToArray();
+#if NET461_OR_GREATER || NETSTANDARD2_0
+            var doubleValue = BitConverter.ToDouble(doubleBuff,0);
+#else
+            var doubleValue = BitConverter.ToDouble(doubleBuff);
+#endif
+            _readPos += 8;
+            return doubleValue;
+        }
+
+        public string GetStr()
+        {
+            var length = GetInt();
+            var strBuff = _buffer[_readPos..(_readPos + length)];
+            var strValue = Encoding.UTF8.GetString(strBuff);
+            _readPos += length;
+            return strValue;
+        }
+
+        public byte[] GetBuffer()
+        {
+            return _buffer[.._writePos];
+        }
+
+        private void ExtendBuffer(int spaceNeed)
+        {
+            if (_writePos + spaceNeed >= _totalLength)
+            {
+                _totalLength = Math.Max(spaceNeed, _totalLength);
+                var newBuffer = new byte[_totalLength * 2];
+                _buffer.CopyTo(newBuffer, 0);
+                _buffer = newBuffer;
+                _totalLength = 2 * _totalLength;
+            }
+        }
+
+        // these for write
+        public void AddBool(bool value)
+        {
+            var boolBuffer = BitConverter.GetBytes(value);
+
+            if (_isLittleEndian) boolBuffer = boolBuffer.Reverse().ToArray();
+
+            ExtendBuffer(boolBuffer.Length);
+            boolBuffer.CopyTo(_buffer, _writePos);
+            _writePos += boolBuffer.Length;
+        }
+
+        public void AddInt(int value)
+        {
+            var intBuff = BitConverter.GetBytes(value);
+
+            if (_isLittleEndian) intBuff = intBuff.Reverse().ToArray();
+
+            ExtendBuffer(intBuff.Length);
+            intBuff.CopyTo(_buffer, _writePos);
+            _writePos += intBuff.Length;
+        }
+
+        public void AddLong(long value)
+        {
+            var longBuff = BitConverter.GetBytes(value);
+
+            if (_isLittleEndian) longBuff = longBuff.Reverse().ToArray();
+
+            ExtendBuffer(longBuff.Length);
+            longBuff.CopyTo(_buffer, _writePos);
+            _writePos += longBuff.Length;
+        }
+
+        public void AddFloat(float value)
+        {
+            var floatBuff = BitConverter.GetBytes(value);
+
+            if (_isLittleEndian) floatBuff = floatBuff.Reverse().ToArray();
+
+            ExtendBuffer(floatBuff.Length);
+            floatBuff.CopyTo(_buffer, _writePos);
+            _writePos += floatBuff.Length;
+        }
+
+        public void AddDouble(double value)
+        {
+            var doubleBuff = BitConverter.GetBytes(value);
+
+            if (_isLittleEndian) doubleBuff = doubleBuff.Reverse().ToArray();
+
+            ExtendBuffer(doubleBuff.Length);
+            doubleBuff.CopyTo(_buffer, _writePos);
+            _writePos += doubleBuff.Length;
+        }
+
+        public void AddStr(string value)
+        {
+            var strBuf = Encoding.UTF8.GetBytes(value);
+
+            AddInt(strBuf.Length);
+
+            ExtendBuffer(strBuf.Length);
+            strBuf.CopyTo(_buffer, _writePos);
+            _writePos += strBuf.Length;
+        }
+
+        public void AddChar(char value)
+        {
+            var charBuf = BitConverter.GetBytes(value);
+
+            if (_isLittleEndian) charBuf = charBuf.Reverse().ToArray();
+
+            ExtendBuffer(charBuf.Length);
+            charBuf.CopyTo(_buffer, _writePos);
+            _writePos += charBuf.Length;
+        }
+        public void AddByte(byte value)
+        {
+            ExtendBuffer(1);
+            _buffer[_writePos] = value;
+            _writePos += 1;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB/DataStructure/GetSubArray.cs b/src/Apache.IoTDB/DataStructure/GetSubArray.cs
new file mode 100644
index 0000000..0f4cfa5
--- /dev/null
+++ b/src/Apache.IoTDB/DataStructure/GetSubArray.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#if NET461_OR_GREATER || NETSTANDARD2_0
+//https://github.com/bgrainger/IndexRange
+//https://gist.github.com/bgrainger/fb2c18659c2cdfce494c82a8c4803360
+
+namespace System.Runtime.CompilerServices
+{
+    internal static class RuntimeHelpers
+    {
+        /// <summary>
+        /// Slices the specified array using the specified range.
+        /// </summary>
+        public static T[] GetSubArray<T>(T[] array, Range range)
+        {
+            if (array == null)
+            {
+                throw new ArgumentNullException();
+            }
+
+            (int offset, int length) = range.GetOffsetAndLength(array.Length);
+
+            if (default(T)! != null || typeof(T[]) == array.GetType()) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
+            {
+                // We know the type of the array to be exactly T[].
+
+                if (length == 0)
+                {
+                    return Array.Empty<T>();
+                }
+
+                var dest = new T[length];
+                Array.Copy(array, offset, dest, 0, length);
+                return dest;
+            }
+            else
+            {
+                // The array is actually a U[] where U:T.
+                T[] dest = (T[])Array.CreateInstance(array.GetType().GetElementType()!, length);
+                Array.Copy(array, offset, dest, 0, length);
+                return dest;
+            }
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/src/Apache.IoTDB/DataStructure/RowRecord.cs b/src/Apache.IoTDB/DataStructure/RowRecord.cs
new file mode 100644
index 0000000..902c442
--- /dev/null
+++ b/src/Apache.IoTDB/DataStructure/RowRecord.cs
@@ -0,0 +1,212 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Thrift;
+
+namespace Apache.IoTDB.DataStructure
+{
+    public class RowRecord
+    {
+        public long Timestamps { get; }
+        public List<object> Values { get; }
+        public List<string> Measurements { get; }
+
+        public RowRecord(DateTime timestamp, List<object> values, List<string> measurements)
+            :this(new DateTimeOffset(timestamp.ToUniversalTime()).ToUnixTimeMilliseconds(), values,measurements)
+        {
+        }
+        public RowRecord(long timestamps, List<object> values, List<string> measurements)
+        {
+            Timestamps = timestamps;
+            Values = values;
+            Measurements = measurements;
+        }
+
+        public void Append(string measurement, object value)
+        {
+            Values.Add(value);
+            Measurements.Add(measurement);
+        }
+
+        public DateTime GetDateTime()
+        {
+            return DateTimeOffset.FromUnixTimeMilliseconds(Timestamps).DateTime.ToLocalTime();
+        }
+
+        public override string ToString()
+        {
+            var str = "TimeStamp";
+            foreach (var measurement in Measurements)
+            {
+                str += "\t\t";
+                str += measurement;
+            }
+
+            str += "\n";
+
+            str += Timestamps.ToString();
+            foreach (var rowValue in Values)
+            {
+                str += "\t\t";
+                str += rowValue.ToString();
+            }
+
+            return str;
+        }
+
+        public List<int> GetDataTypes()
+        {
+            var dataTypeValues = new List<int>();
+            
+            foreach (var valueType in Values.Select(value => value))
+            {
+                switch (valueType)
+                {
+                    case bool _:
+                        dataTypeValues.Add((int) TSDataType.BOOLEAN);
+                        break;
+                    case int _:
+                        dataTypeValues.Add((int) TSDataType.INT32);
+                        break;
+                    case long _:
+                        dataTypeValues.Add((int) TSDataType.INT64);
+                        break;
+                    case float _:
+                        dataTypeValues.Add((int) TSDataType.FLOAT);
+                        break;
+                    case double _:
+                        dataTypeValues.Add((int) TSDataType.DOUBLE);
+                        break;
+                    case string _:
+                        dataTypeValues.Add((int) TSDataType.TEXT);
+                        break;
+                }
+            }
+
+            return dataTypeValues;
+        }
+        public TypeCode GetTypeCode(int index)
+        {
+            TypeCode tSDataType = TypeCode.Empty;
+            var valueType = Values[index];
+            switch (valueType)
+            {
+                case bool _:
+                    tSDataType = TypeCode.Boolean;
+                    break;
+                case int _:
+                    tSDataType = TypeCode.Int32;
+                    break;
+                case long _:
+                    tSDataType = TypeCode.Int64;
+                    break;
+                case float _:
+                    tSDataType = TypeCode.Single;
+                    break;
+                case double _:
+                    tSDataType = TypeCode.Double;
+                    break;
+                case string _:
+                    tSDataType = TypeCode.String;
+                    break;
+            }
+            return tSDataType;
+        }
+        public Type GetCrlType(int index)
+        {
+            Type tSDataType =  typeof(object);
+            var valueType = Values[index];
+            switch (valueType)
+            {
+                case bool _:
+                    tSDataType = typeof( bool);
+                    break;
+                case int _:
+                    tSDataType = typeof(int);
+                    break;
+                case long _:
+                    tSDataType = typeof(long);
+                    break;
+                case float _:
+                    tSDataType = typeof(float);
+                    break;
+                case double _:
+                    tSDataType = typeof(double);
+                    break;
+                case string _:
+                    tSDataType = typeof(string);
+                    break;
+            }
+            return tSDataType;
+        }
+
+        public TSDataType GetDataType(int index)
+        {
+            TSDataType tSDataType = TSDataType.NONE;
+            var valueType = Values[index];
+            switch (valueType)
+            {
+                case bool _:
+                    tSDataType = TSDataType.BOOLEAN;
+                    break;
+                case int _:
+                    tSDataType = TSDataType.INT32;
+                    break;
+                case long _:
+                    tSDataType = TSDataType.INT64;
+                    break;
+                case float _:
+                    tSDataType = TSDataType.FLOAT;
+                    break;
+                case double _:
+                    tSDataType = TSDataType.DOUBLE;
+                    break;
+                case string _:
+                    tSDataType = TSDataType.TEXT;
+                    break;
+            }
+            return tSDataType;
+        }
+
+
+        public byte[] ToBytes()
+        {
+            var buffer = new ByteBuffer(Values.Count * 8);
+            
+            foreach (var value in Values)
+            {
+                switch (value)
+                {
+                    case bool b:
+                        buffer.AddByte((byte) TSDataType.BOOLEAN);
+                        buffer.AddBool(b);
+                        break;
+                    case int i:
+                        buffer.AddByte((byte) TSDataType.INT32);
+                        buffer.AddInt(i);
+                        break;
+                    case long l:
+                        buffer.AddByte((byte) TSDataType.INT64);
+                        buffer.AddLong(l);
+                        break;
+                    case double d:
+                        buffer.AddByte((byte) TSDataType.DOUBLE);
+                        buffer.AddDouble(d);
+                        break;
+                    case float f:
+                        buffer.AddByte((byte) TSDataType.FLOAT);
+                        buffer.AddFloat(f);
+                        break;
+                    case string s:
+                        buffer.AddByte((byte) TSDataType.TEXT);
+                        buffer.AddStr(s);
+                        break;
+                    default:
+                        throw new TException($"Unsupported data type:{value.GetType()}", null);
+                }
+            }
+
+            return buffer.GetBuffer();;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB/DataStructure/SessionDataSet.cs b/src/Apache.IoTDB/DataStructure/SessionDataSet.cs
new file mode 100644
index 0000000..4cd3380
--- /dev/null
+++ b/src/Apache.IoTDB/DataStructure/SessionDataSet.cs
@@ -0,0 +1,340 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Thrift;
+
+namespace Apache.IoTDB.DataStructure
+{
+    public class SessionDataSet : System.IDisposable
+    {
+        private readonly long _queryId;
+        private readonly long _statementId;
+        private readonly string _sql;
+        private readonly List<string> _columnNames;
+        private readonly Dictionary<string, int> _columnNameIndexMap;
+        private readonly Dictionary<int, int> _duplicateLocation;
+        private readonly List<string> _columnTypeLst;
+        private TSQueryDataSet _queryDataset;
+        private readonly byte[] _currentBitmap;
+        private readonly int _columnSize;
+        private List<ByteBuffer> _valueBufferLst, _bitmapBufferLst;
+        private ByteBuffer _timeBuffer;
+        private readonly ConcurrentClientQueue _clientQueue;
+        private int _rowIndex;
+        private bool _hasCatchedResult;
+        private RowRecord _cachedRowRecord;
+        private bool _isClosed = false;
+        private bool disposedValue;
+
+        private string TimestampStr => "Time";
+        private int StartIndex => 2;
+        private int Flag => 0x80;
+        private int DefaultTimeout => 10000;
+        public int FetchSize { get; set; }
+        public int RowCount { get; set; }
+        public SessionDataSet(string sql, TSExecuteStatementResp resp, ConcurrentClientQueue clientQueue, long statementId)
+        {
+            _clientQueue = clientQueue;
+            _sql = sql;
+            _queryDataset = resp.QueryDataSet;
+            _queryId = resp.QueryId;
+            _statementId = statementId;
+            _columnSize = resp.Columns.Count;
+            _currentBitmap = new byte[_columnSize];
+            _columnNames = new List<string>();
+            _timeBuffer = new ByteBuffer(_queryDataset.Time);
+            _columnNameIndexMap = new Dictionary<string, int>();
+            _columnTypeLst = new List<string>();
+            _duplicateLocation = new Dictionary<int, int>();
+            _valueBufferLst = new List<ByteBuffer>();
+            _bitmapBufferLst = new List<ByteBuffer>();
+            // some internal variable
+            _hasCatchedResult = false;
+            _rowIndex = 0;
+            RowCount = _queryDataset.Time.Length / sizeof(long);
+            if (resp.ColumnNameIndexMap != null)
+            {
+                for (var index = 0; index < resp.Columns.Count; index++)
+                {
+                    _columnNames.Add("");
+                    _columnTypeLst.Add("");
+                }
+
+                for (var index = 0; index < resp.Columns.Count; index++)
+                {
+                    var name = resp.Columns[index];
+                    _columnNames[resp.ColumnNameIndexMap[name]] = name;
+                    _columnTypeLst[resp.ColumnNameIndexMap[name]] = resp.DataTypeList[index];
+                }
+            }
+            else
+            {
+                _columnNames = resp.Columns;
+                _columnTypeLst = resp.DataTypeList;
+            }
+
+            for (int index = 0; index < _columnNames.Count; index++)
+            {
+                var columnName = _columnNames[index];
+                if (_columnNameIndexMap.ContainsKey(columnName))
+                {
+                    _duplicateLocation[index] = _columnNameIndexMap[columnName];
+                }
+                else
+                {
+                    _columnNameIndexMap[columnName] = index;
+                }
+
+                _valueBufferLst.Add(new ByteBuffer(_queryDataset.ValueList[index]));
+                _bitmapBufferLst.Add(new ByteBuffer(_queryDataset.BitmapList[index]));
+            }
+
+        }
+        public List<string> ColumnNames => _columnNames;
+
+
+        private List<string> GetColumnNames()
+        {
+            var lst = new List<string>
+            {
+                "timestamp"
+            };
+            lst.AddRange(_columnNames);
+            return lst;
+        }
+
+        public void ShowTableNames()
+        {
+            var str = GetColumnNames()
+                .Aggregate("", (current, name) => current + (name + "\t\t"));
+
+            Console.WriteLine(str);
+        }
+
+        public bool HasNext()
+        {
+            if (_hasCatchedResult)
+            {
+                return true;
+            }
+
+            // we have consumed all current data, fetch some more
+            if (!_timeBuffer.HasRemaining())
+            {
+                if (!FetchResults())
+                {
+                    return false;
+                }
+            }
+
+            ConstructOneRow();
+            _hasCatchedResult = true;
+            return true;
+        }
+
+        public RowRecord Next()
+        {
+            if (!_hasCatchedResult)
+            {
+                if (!HasNext())
+                {
+                    return null;
+                }
+            }
+
+            _hasCatchedResult = false;
+            return _cachedRowRecord;
+        }
+        public RowRecord GetRow()
+        {
+            return _cachedRowRecord;
+        }
+
+        private TSDataType GetDataTypeFromStr(string str)
+        {
+            return str switch
+            {
+                "BOOLEAN" => TSDataType.BOOLEAN,
+                "INT32" => TSDataType.INT32,
+                "INT64" => TSDataType.INT64,
+                "FLOAT" => TSDataType.FLOAT,
+                "DOUBLE" => TSDataType.DOUBLE,
+                "TEXT" => TSDataType.TEXT,
+                "NULLTYPE" => TSDataType.NONE,
+                _ => TSDataType.TEXT
+            };
+        }
+
+        private void ConstructOneRow()
+        {
+            List<object> fieldLst = new List<Object>();
+
+            for (int i = 0; i < _columnSize; i++)
+            {
+                if (_duplicateLocation.ContainsKey(i))
+                {
+                    var field = fieldLst[_duplicateLocation[i]];
+                    fieldLst.Add(field);
+                }
+                else
+                {
+                    var columnValueBuffer = _valueBufferLst[i];
+                    var columnBitmapBuffer = _bitmapBufferLst[i];
+
+                    if (_rowIndex % 8 == 0)
+                    {
+                        _currentBitmap[i] = columnBitmapBuffer.GetByte();
+                    }
+
+                    object localField;
+                    if (!IsNull(i, _rowIndex))
+                    {
+                        var columnDataType = GetDataTypeFromStr(_columnTypeLst[i]);
+
+
+                        switch (columnDataType)
+                        {
+                            case TSDataType.BOOLEAN:
+                                localField = columnValueBuffer.GetBool();
+                                break;
+                            case TSDataType.INT32:
+                                localField = columnValueBuffer.GetInt();
+                                break;
+                            case TSDataType.INT64:
+                                localField = columnValueBuffer.GetLong();
+                                break;
+                            case TSDataType.FLOAT:
+                                localField = columnValueBuffer.GetFloat();
+                                break;
+                            case TSDataType.DOUBLE:
+                                localField = columnValueBuffer.GetDouble();
+                                break;
+                            case TSDataType.TEXT:
+                                localField = columnValueBuffer.GetStr();
+                                break;
+                            default:
+                                string err_msg = "value format not supported";
+                                throw new TException(err_msg, null);
+                        }
+
+                        fieldLst.Add(localField);
+                    }
+                    else
+                    {
+                        localField = null;
+                        fieldLst.Add(DBNull.Value);
+                    }
+                }
+            }
+
+            long timestamp = _timeBuffer.GetLong();
+            _rowIndex += 1;
+            _cachedRowRecord = new RowRecord(timestamp, fieldLst, _columnNames);
+        }
+
+        private bool IsNull(int loc, int row_index)
+        {
+            byte bitmap = _currentBitmap[loc];
+            int shift = row_index % 8;
+            return ((Flag >> shift) & bitmap) == 0;
+        }
+
+        private bool FetchResults()
+        {
+            _rowIndex = 0;
+            var myClient = _clientQueue.Take();
+            var req = new TSFetchResultsReq(myClient.SessionId, _sql, FetchSize, _queryId, true)
+            {
+                Timeout = DefaultTimeout
+            };
+            try
+            {
+                var task = myClient.ServiceClient.fetchResultsAsync(req);
+
+                var resp = task.ConfigureAwait(false).GetAwaiter().GetResult();
+
+                if (resp.HasResultSet)
+                {
+                    _queryDataset = resp.QueryDataSet;
+                    // reset buffer
+                    _timeBuffer = new ByteBuffer(resp.QueryDataSet.Time);
+                    _valueBufferLst = new List<ByteBuffer>();
+                    _bitmapBufferLst = new List<ByteBuffer>();
+                    for (int index = 0; index < _queryDataset.ValueList.Count; index++)
+                    {
+                        _valueBufferLst.Add(new ByteBuffer(_queryDataset.ValueList[index]));
+                        _bitmapBufferLst.Add(new ByteBuffer(_queryDataset.BitmapList[index]));
+                    }
+
+                    // reset row index
+                    _rowIndex = 0;
+                }
+
+                return resp.HasResultSet;
+            }
+            catch (TException e)
+            {
+                throw new TException("Cannot fetch result from server, because of network connection", e);
+            }
+            finally
+            {
+                _clientQueue.Add(myClient);
+            }
+        }
+
+        public async Task Close()
+        {
+            if (!_isClosed)
+            {
+                var myClient = _clientQueue.Take();
+                var req = new TSCloseOperationReq(myClient.SessionId)
+                {
+                    QueryId = _queryId,
+                    StatementId = _statementId
+                };
+
+                try
+                {
+                    var status = await myClient.ServiceClient.closeOperationAsync(req);
+                }
+                catch (TException e)
+                {
+                    throw new TException("Operation Handle Close Failed", e);
+                }
+                finally
+                {
+                    _clientQueue.Add(myClient);
+                }
+            }
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    try
+                    {
+                        this.Close().Wait();
+                    }
+                    catch
+                    {
+                    }
+                }
+                _queryDataset = null;
+                _timeBuffer = null;
+                _valueBufferLst = null;
+                _bitmapBufferLst = null;
+                disposedValue = true;
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(disposing: true);
+            GC.SuppressFinalize(this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB/DataStructure/Tablet.cs b/src/Apache.IoTDB/DataStructure/Tablet.cs
new file mode 100644
index 0000000..9d67b5d
--- /dev/null
+++ b/src/Apache.IoTDB/DataStructure/Tablet.cs
@@ -0,0 +1,352 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using Thrift;
+
+namespace Apache.IoTDB.DataStructure
+{
+    /*
+    * A tablet data of one device, the tablet contains multiple measurements of this device that share
+    * the same time column.
+    *
+    * for example:  device root.sg1.d1
+    *
+    * time, m1, m2, m3
+    *    1,  1,  2,  3
+    *    2,  1,  2,  3
+    *    3,  1,  2,  3
+    *
+    * @deprecated
+    * Notice: The tablet should not have empty cell
+    * 
+    * From 0.13 IoTDB Server, tablet could have empty cell
+    *
+    */
+    public class Tablet
+    {
+        private readonly List<long> _timestamps;
+        private readonly List<List<object>> _values;
+
+        public string DeviceId { get; }
+        public List<string> Measurements { get; }
+        public List<TSDataType> DataTypes { get; }
+        public BitMap[] BitMaps;
+        public int RowNumber { get; }
+        public int ColNumber { get; }
+
+        private readonly Utils _utilFunctions = new Utils();
+
+        public Tablet(
+            string deviceId,
+            List<string> measurements,
+            List<TSDataType> dataTypes,
+            List<List<object>> values,
+            List<long> timestamps)
+        {
+            if (timestamps.Count != values.Count)
+            {
+                throw new Exception(
+                    $"Input error. Timestamps.Count({timestamps.Count}) does not equal to Values.Count({values.Count}).",
+                    null);
+            }
+
+            if (measurements.Count != dataTypes.Count)
+            {
+                throw new Exception(
+                    $"Input error. Measurements.Count({measurements.Count}) does not equal to DataTypes.Count({dataTypes.Count}).",
+                    null);
+            }
+
+            if (!_utilFunctions.IsSorted(timestamps))
+            {
+                var sorted = timestamps
+                    .Select((x, index) => (timestamp: x, values: values[index]))
+                    .OrderBy(x => x.timestamp).ToList();
+
+                _timestamps = sorted.Select(x => x.timestamp).ToList();
+                _values = sorted.Select(x => x.values).ToList();
+            }
+            else
+            {
+                _values = values;
+                _timestamps = timestamps;
+            }
+
+            DeviceId = deviceId;
+            Measurements = measurements;
+            DataTypes = dataTypes;
+            RowNumber = timestamps.Count;
+            ColNumber = measurements.Count;
+
+            // reset bitmap
+            if (BitMaps != null)
+            {
+                foreach (var bitmap in BitMaps)
+                {
+                    if (bitmap != null)
+                    {
+                        bitmap.reset();
+                    }
+                }
+            }
+        }
+        public Tablet(
+            string deviceId,
+            List<string> measurements,
+            List<List<object>> values,
+            List<long> timestamps)
+        {
+            if (timestamps.Count != values.Count)
+            {
+                throw new Exception(
+                    $"Input error. Timestamps.Count({timestamps.Count}) does not equal to Values.Count({values.Count}).",
+                    null);
+            }
+            if (!_utilFunctions.IsSorted(timestamps))
+            {
+                var sorted = timestamps
+                    .Select((x, index) => (timestamp: x, values: values[index]))
+                    .OrderBy(x => x.timestamp).ToList();
+
+                _timestamps = sorted.Select(x => x.timestamp).ToList();
+                _values = sorted.Select(x => x.values).ToList();
+            }
+            else
+            {
+                _values = values;
+                _timestamps = timestamps;
+            }
+
+            DeviceId = deviceId;
+            Measurements = measurements;
+            RowNumber = timestamps.Count;
+            ColNumber = measurements.Count;
+            DataTypes = new List<TSDataType>();
+            for (int i = 0; i < ColNumber; i++)
+            {
+                bool columnAllNull = true;
+                for (int j = 0; j < RowNumber; j++)
+                {
+                    if (_values[j][i] != null)
+                    {
+                        switch (_values[j][i])
+                        {
+                            case bool _:
+                                DataTypes.Add(TSDataType.BOOLEAN);
+                                break;
+                            case int _:
+                                DataTypes.Add(TSDataType.INT32);
+                                break;
+                            case long _:
+                                DataTypes.Add(TSDataType.INT64);
+                                break;
+                            case float _:
+                                DataTypes.Add(TSDataType.FLOAT);
+                                break;
+                            case double _:
+                                DataTypes.Add(TSDataType.DOUBLE);
+                                break;
+                            case string _:
+                                DataTypes.Add(TSDataType.TEXT);
+                                break;
+                            default:
+                                throw new Exception(
+                                    $"Input error. Data type {_values[j][i].GetType().Name} is not supported.",
+                                    null);
+                        }
+                        columnAllNull = false;
+                        break;
+                    }
+                }
+                if (columnAllNull)
+                {
+                    throw new Exception($"Input error. Column {measurements[i]} of device {deviceId} is empty.", null);
+                }
+            }
+
+            // reset bitmap
+            if (BitMaps != null)
+            {
+                foreach (var bitmap in BitMaps)
+                {
+                    if (bitmap != null)
+                    {
+                        bitmap.reset();
+                    }
+                }
+            }
+        }
+
+        public byte[] GetBinaryTimestamps()
+        {
+            var buffer = new ByteBuffer(new byte[] { });
+
+            foreach (var timestamp in _timestamps)
+            {
+                buffer.AddLong(timestamp);
+            }
+
+            return buffer.GetBuffer();
+        }
+
+        public List<int> GetDataTypes()
+        {
+            var dataTypeValues = DataTypes.ConvertAll(x => (int)x);
+
+            return dataTypeValues;
+        }
+
+        private int EstimateBufferSize()
+        {
+            var estimateSize = 0;
+
+            // estimate one row size
+            foreach (var dataType in DataTypes)
+            {
+                switch (dataType)
+                {
+                    case TSDataType.BOOLEAN:
+                        estimateSize += 1;
+                        break;
+                    case TSDataType.INT32:
+                        estimateSize += 4;
+                        break;
+                    case TSDataType.INT64:
+                        estimateSize += 8;
+                        break;
+                    case TSDataType.FLOAT:
+                        estimateSize += 4;
+                        break;
+                    case TSDataType.DOUBLE:
+                        estimateSize += 8;
+                        break;
+                    case TSDataType.TEXT:
+                        estimateSize += 8;
+                        break;
+                    default:
+                        throw new Exception(
+                            $"Input error. Data type {dataType} is not supported.",
+                            null);
+                }
+            }
+
+            estimateSize *= _timestamps.Count;
+            return estimateSize;
+        }
+
+        public byte[] GetBinaryValues()
+        {
+            var estimateSize = EstimateBufferSize();
+            // Console.WriteLine("Estimate size : {0}", estimateSize);
+            var buffer = new ByteBuffer(estimateSize);
+
+            for (var i = 0; i < ColNumber; i++)
+            {
+                var dataType = DataTypes[i];
+
+                // set bitmap
+                for (var j = 0; j < RowNumber; j++)
+                {
+                    var value = _values[j][i];
+                    if (value == null)
+                    {
+                        if (BitMaps == null)
+                        {
+                            BitMaps = new BitMap[ColNumber];
+                        }
+                        if (BitMaps[i] == null)
+                        {
+                            BitMaps[i] = new BitMap(RowNumber);
+                        }
+                        BitMaps[i].mark(j);
+                    }
+                }
+
+                switch (dataType)
+                {
+                    case TSDataType.BOOLEAN:
+                        {
+                            for (int j = 0; j < RowNumber; j++)
+                            {
+                                var value = _values[j][i];
+                                buffer.AddBool(value != null ? (bool)value : false);
+                            }
+
+                            break;
+                        }
+                    case TSDataType.INT32:
+                        {
+                            for (int j = 0; j < RowNumber; j++)
+                            {
+                                var value = _values[j][i];
+                                buffer.AddInt(value != null ? (int)value : int.MinValue);
+                            }
+
+                            break;
+                        }
+                    case TSDataType.INT64:
+                        {
+                            for (int j = 0; j < RowNumber; j++)
+                            {
+                                var value = _values[j][i];
+                                buffer.AddLong(value != null ? (long)value : long.MinValue);
+                            }
+
+                            break;
+                        }
+                    case TSDataType.FLOAT:
+                        {
+                            for (int j = 0; j < RowNumber; j++)
+                            {
+                                var value = _values[j][i];
+                                buffer.AddFloat(value != null ? (float)value : float.MinValue);
+                            }
+
+                            break;
+                        }
+                    case TSDataType.DOUBLE:
+                        {
+                            for (int j = 0; j < RowNumber; j++)
+                            {
+                                var value = _values[j][i];
+                                buffer.AddDouble(value != null ? (double)value : double.MinValue);
+                            }
+
+                            break;
+                        }
+                    case TSDataType.TEXT:
+                        {
+                            for (int j = 0; j < RowNumber; j++)
+                            {
+                                var value = _values[j][i];
+                                buffer.AddStr(value != null ? (string)value : string.Empty);
+                            }
+
+                            break;
+                        }
+                    default:
+                        throw new Exception($"Unsupported data type {dataType}", null);
+                }
+            }
+            if (BitMaps != null)
+            {
+                foreach (var bitmap in BitMaps)
+                {
+                    bool columnHasNull = bitmap != null && !bitmap.isAllUnmarked();
+                    buffer.AddBool((bool)columnHasNull);
+                    if (columnHasNull)
+                    {
+                        var bytes = bitmap.getByteArray();
+                        for (int i = 0; i < RowNumber / 8 + 1; i++)
+                        {
+                            buffer.AddByte(bytes[i]);
+                        }
+                    }
+                }
+            }
+
+            return buffer.GetBuffer();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB/IoTDBConstants.cs b/src/Apache.IoTDB/IoTDBConstants.cs
new file mode 100644
index 0000000..c21299b
--- /dev/null
+++ b/src/Apache.IoTDB/IoTDBConstants.cs
@@ -0,0 +1,71 @@
+namespace Apache.IoTDB
+{
+    public enum TSDataType
+    {
+        BOOLEAN,
+        INT32,
+        INT64,
+        FLOAT,
+        DOUBLE,
+        TEXT,
+
+        // default value must be 0
+        NONE
+    }
+
+    public enum TSEncoding
+    {
+        PLAIN,
+        PLAIN_DICTIONARY,
+        RLE,
+        DIFF,
+        TS_2DIFF,
+        BITMAP,
+        GORILLA_V1,
+        REGULAR,
+        GORILLA,
+
+        // default value must be 0
+        NONE
+    }
+
+    public enum Compressor
+    {
+        UNCOMPRESSED,
+        SNAPPY,
+        GZIP,
+        LZO,
+        SDT,
+        PAA,
+        PLA,
+        LZ4
+    }
+    public enum TemplateQueryType
+    {
+        COUNT_MEASUREMENTS,
+        IS_MEASUREMENT,
+        PATH_EXIST,
+        SHOW_MEASUREMENTS,
+        SHOW_TEMPLATES,
+        SHOW_SET_TEMPLATES,
+        SHOW_USING_TEMPLATES
+    }
+    public class TsFileConstant
+    {
+
+        public static string TSFILE_SUFFIX = ".tsfile";
+        public static string TSFILE_HOME = "TSFILE_HOME";
+        public static string TSFILE_CONF = "TSFILE_CONF";
+        public static string PATH_ROOT = "root";
+        public static string TMP_SUFFIX = "tmp";
+        public static string PATH_SEPARATOR = ".";
+        public static char PATH_SEPARATOR_CHAR = '.';
+        public static string PATH_SEPARATER_NO_REGEX = "\\.";
+        public static char DOUBLE_QUOTE = '"';
+
+        public static byte TIME_COLUMN_MASK = (byte)0x80;
+        public static byte VALUE_COLUMN_MASK = (byte)0x40;
+
+        private TsFileConstant() { }
+    }
+}
\ No newline at end of file
diff --git a/src/Apache.IoTDB/Rpc/Generated/IClientRPCService.cs b/src/Apache.IoTDB/Rpc/Generated/IClientRPCService.cs
new file mode 100644
index 0000000..b0cdf09
--- /dev/null
+++ b/src/Apache.IoTDB/Rpc/Generated/IClientRPCService.cs
@@ -0,0 +1,19979 @@
+/**
+ * Autogenerated by Thrift Compiler (0.14.2)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Thrift;
+using Thrift.Collections;
+
+using Thrift.Protocol;
+using Thrift.Protocol.Entities;
+using Thrift.Protocol.Utilities;
+using Thrift.Transport;
+using Thrift.Transport.Client;
+using Thrift.Transport.Server;
+using Thrift.Processor;
+
+
+#pragma warning disable IDE0079  // remove unnecessary pragmas
+#pragma warning disable IDE1006  // parts of the code use IDL spelling
+
+public partial class IClientRPCService
+{
+  public interface IAsync
+  {
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeQueryStatementV2Async(TSExecuteStatementReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeUpdateStatementV2Async(TSExecuteStatementReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeStatementV2Async(TSExecuteStatementReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeRawDataQueryV2Async(TSRawDataQueryReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeLastDataQueryV2Async(TSLastDataQueryReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSFetchResultsResp> fetchResultsV2Async(TSFetchResultsReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSOpenSessionResp> openSessionAsync(TSOpenSessionReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> closeSessionAsync(TSCloseSessionReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeStatementAsync(TSExecuteStatementReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> executeBatchStatementAsync(TSExecuteBatchStatementReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeQueryStatementAsync(TSExecuteStatementReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeUpdateStatementAsync(TSExecuteStatementReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSFetchResultsResp> fetchResultsAsync(TSFetchResultsReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSFetchMetadataResp> fetchMetadataAsync(TSFetchMetadataReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> cancelOperationAsync(TSCancelOperationReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> closeOperationAsync(TSCloseOperationReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSGetTimeZoneResp> getTimeZoneAsync(long sessionId, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> setTimeZoneAsync(TSSetTimeZoneReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<ServerProperties> getPropertiesAsync(CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> setStorageGroupAsync(long sessionId, string storageGroup, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> createTimeseriesAsync(TSCreateTimeseriesReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> createAlignedTimeseriesAsync(TSCreateAlignedTimeseriesReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> createMultiTimeseriesAsync(TSCreateMultiTimeseriesReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> deleteTimeseriesAsync(long sessionId, List<string> path, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> deleteStorageGroupsAsync(long sessionId, List<string> storageGroup, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> insertRecordAsync(TSInsertRecordReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> insertStringRecordAsync(TSInsertStringRecordReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> insertTabletAsync(TSInsertTabletReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> insertTabletsAsync(TSInsertTabletsReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> insertRecordsAsync(TSInsertRecordsReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> insertRecordsOfOneDeviceAsync(TSInsertRecordsOfOneDeviceReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> insertStringRecordsOfOneDeviceAsync(TSInsertStringRecordsOfOneDeviceReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> insertStringRecordsAsync(TSInsertStringRecordsReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> testInsertTabletAsync(TSInsertTabletReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> testInsertTabletsAsync(TSInsertTabletsReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> testInsertRecordAsync(TSInsertRecordReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> testInsertStringRecordAsync(TSInsertStringRecordReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> testInsertRecordsAsync(TSInsertRecordsReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> testInsertRecordsOfOneDeviceAsync(TSInsertRecordsOfOneDeviceReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> testInsertStringRecordsAsync(TSInsertStringRecordsReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> deleteDataAsync(TSDeleteDataReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeRawDataQueryAsync(TSRawDataQueryReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeLastDataQueryAsync(TSLastDataQueryReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<long> requestStatementIdAsync(long sessionId, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> createSchemaTemplateAsync(TSCreateSchemaTemplateReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> appendSchemaTemplateAsync(TSAppendSchemaTemplateReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> pruneSchemaTemplateAsync(TSPruneSchemaTemplateReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSQueryTemplateResp> querySchemaTemplateAsync(TSQueryTemplateReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> setSchemaTemplateAsync(TSSetSchemaTemplateReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> unsetSchemaTemplateAsync(TSUnsetSchemaTemplateReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> dropSchemaTemplateAsync(TSDropSchemaTemplateReq req, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> handshakeAsync(TSyncIdentityInfo info, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> sendPipeDataAsync(byte[] buff, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSStatus> sendFileAsync(TSyncTransportMetaInfo metaInfo, byte[] buff, CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSBackupConfigurationResp> getBackupConfigurationAsync(CancellationToken cancellationToken = default);
+
+    global::System.Threading.Tasks.Task<TSConnectionInfoResp> fetchAllConnectionsInfoAsync(CancellationToken cancellationToken = default);
+
+  }
+
+
+  public class Client : TBaseClient, IDisposable, IAsync
+  {
+    public Client(TProtocol protocol) : this(protocol, protocol)
+    {
+    }
+
+    public Client(TProtocol inputProtocol, TProtocol outputProtocol) : base(inputProtocol, outputProtocol)    {
+    }
+    public async global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeQueryStatementV2Async(TSExecuteStatementReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("executeQueryStatementV2", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.executeQueryStatementV2Args() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.executeQueryStatementV2Result();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "executeQueryStatementV2 failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeUpdateStatementV2Async(TSExecuteStatementReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("executeUpdateStatementV2", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.executeUpdateStatementV2Args() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.executeUpdateStatementV2Result();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "executeUpdateStatementV2 failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeStatementV2Async(TSExecuteStatementReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("executeStatementV2", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.executeStatementV2Args() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.executeStatementV2Result();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "executeStatementV2 failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeRawDataQueryV2Async(TSRawDataQueryReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("executeRawDataQueryV2", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.executeRawDataQueryV2Args() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.executeRawDataQueryV2Result();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "executeRawDataQueryV2 failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeLastDataQueryV2Async(TSLastDataQueryReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("executeLastDataQueryV2", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.executeLastDataQueryV2Args() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.executeLastDataQueryV2Result();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "executeLastDataQueryV2 failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSFetchResultsResp> fetchResultsV2Async(TSFetchResultsReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("fetchResultsV2", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.fetchResultsV2Args() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.fetchResultsV2Result();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "fetchResultsV2 failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSOpenSessionResp> openSessionAsync(TSOpenSessionReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("openSession", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.openSessionArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.openSessionResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "openSession failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> closeSessionAsync(TSCloseSessionReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("closeSession", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.closeSessionArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.closeSessionResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "closeSession failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeStatementAsync(TSExecuteStatementReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("executeStatement", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.executeStatementArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.executeStatementResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "executeStatement failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> executeBatchStatementAsync(TSExecuteBatchStatementReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("executeBatchStatement", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.executeBatchStatementArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.executeBatchStatementResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "executeBatchStatement failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeQueryStatementAsync(TSExecuteStatementReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("executeQueryStatement", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.executeQueryStatementArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.executeQueryStatementResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "executeQueryStatement failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSExecuteStatementResp> executeUpdateStatementAsync(TSExecuteStatementReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("executeUpdateStatement", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.executeUpdateStatementArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.executeUpdateStatementResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "executeUpdateStatement failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSFetchResultsResp> fetchResultsAsync(TSFetchResultsReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("fetchResults", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.fetchResultsArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.fetchResultsResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "fetchResults failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSFetchMetadataResp> fetchMetadataAsync(TSFetchMetadataReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("fetchMetadata", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.fetchMetadataArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.fetchMetadataResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "fetchMetadata failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> cancelOperationAsync(TSCancelOperationReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("cancelOperation", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.cancelOperationArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.cancelOperationResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "cancelOperation failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> closeOperationAsync(TSCloseOperationReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("closeOperation", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.closeOperationArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.closeOperationResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "closeOperation failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSGetTimeZoneResp> getTimeZoneAsync(long sessionId, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("getTimeZone", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.getTimeZoneArgs() {
+        SessionId = sessionId,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.getTimeZoneResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "getTimeZone failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> setTimeZoneAsync(TSSetTimeZoneReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("setTimeZone", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.setTimeZoneArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.setTimeZoneResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "setTimeZone failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<ServerProperties> getPropertiesAsync(CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("getProperties", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.getPropertiesArgs() {
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.getPropertiesResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "getProperties failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> setStorageGroupAsync(long sessionId, string storageGroup, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("setStorageGroup", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.setStorageGroupArgs() {
+        SessionId = sessionId,
+        StorageGroup = storageGroup,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.setStorageGroupResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "setStorageGroup failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> createTimeseriesAsync(TSCreateTimeseriesReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("createTimeseries", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.createTimeseriesArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.createTimeseriesResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "createTimeseries failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> createAlignedTimeseriesAsync(TSCreateAlignedTimeseriesReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("createAlignedTimeseries", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.createAlignedTimeseriesArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.createAlignedTimeseriesResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "createAlignedTimeseries failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> createMultiTimeseriesAsync(TSCreateMultiTimeseriesReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("createMultiTimeseries", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.createMultiTimeseriesArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.createMultiTimeseriesResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "createMultiTimeseries failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> deleteTimeseriesAsync(long sessionId, List<string> path, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("deleteTimeseries", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.deleteTimeseriesArgs() {
+        SessionId = sessionId,
+        Path = path,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.deleteTimeseriesResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "deleteTimeseries failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> deleteStorageGroupsAsync(long sessionId, List<string> storageGroup, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("deleteStorageGroups", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.deleteStorageGroupsArgs() {
+        SessionId = sessionId,
+        StorageGroup = storageGroup,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.deleteStorageGroupsResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "deleteStorageGroups failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> insertRecordAsync(TSInsertRecordReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("insertRecord", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.insertRecordArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.insertRecordResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "insertRecord failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> insertStringRecordAsync(TSInsertStringRecordReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("insertStringRecord", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.insertStringRecordArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.insertStringRecordResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "insertStringRecord failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> insertTabletAsync(TSInsertTabletReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("insertTablet", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.insertTabletArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.insertTabletResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "insertTablet failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> insertTabletsAsync(TSInsertTabletsReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("insertTablets", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.insertTabletsArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.insertTabletsResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "insertTablets failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> insertRecordsAsync(TSInsertRecordsReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("insertRecords", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.insertRecordsArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.insertRecordsResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "insertRecords failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> insertRecordsOfOneDeviceAsync(TSInsertRecordsOfOneDeviceReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("insertRecordsOfOneDevice", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.insertRecordsOfOneDeviceArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.insertRecordsOfOneDeviceResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "insertRecordsOfOneDevice failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> insertStringRecordsOfOneDeviceAsync(TSInsertStringRecordsOfOneDeviceReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("insertStringRecordsOfOneDevice", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.insertStringRecordsOfOneDeviceArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.insertStringRecordsOfOneDeviceResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
+      throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "insertStringRecordsOfOneDevice failed: unknown result");
+    }
+
+    public async global::System.Threading.Tasks.Task<TSStatus> insertStringRecordsAsync(TSInsertStringRecordsReq req, CancellationToken cancellationToken = default)
+    {
+      await OutputProtocol.WriteMessageBeginAsync(new TMessage("insertStringRecords", TMessageType.Call, SeqId), cancellationToken);
+      
+      var args = new InternalStructs.insertStringRecordsArgs() {
+        Req = req,
+      };
+      
+      await args.WriteAsync(OutputProtocol, cancellationToken);
+      await OutputProtocol.WriteMessageEndAsync(cancellationToken);
+      await OutputProtocol.Transport.FlushAsync(cancellationToken);
+      
+      var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);
+      if (msg.Type == TMessageType.Exception)
+      {
+        var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);
+        await InputProtocol.ReadMessageEndAsync(cancellationToken);
+        throw x;
+      }
+
+      var result = new InternalStructs.insertStringRecordsResult();
+      await result.ReadAsync(InputProtocol, cancellationToken);
+      await InputProtocol.ReadMessageEndAsync(cancellationToken);
+      if (result.__isset.success)
+      {
+        return result.Success;
+      }
... 42912 lines suppressed ...