Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Cannot load data using DataTable.Load due to "DataSet does not support System.Nullable<>" error #539

Open
Hermholtz opened this issue Oct 30, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@Hermholtz
Copy link

Current Behavior

Using the following code:

using var connection = new ClickHouseConnection(
  "Host=127.0.0.1;Protocol=http;Port=8123;Username=default;Password=password;Database=default");

string sql = "SELECT * from system.tables";

using var command = connection.CreateCommand();
command.CommandText = sql;

using var reader = command.ExecuteReader();

var table = new DataTable();

try {
	table.Load(reader);
}
catch (Exception e)
{
	Console.WriteLine(e);

	var nullableColumns = reader.GetSchemaTable().Rows.Cast<DataRow>().Where(r => ((Type)r["DataType"]).Name.StartsWith("Nullable"));

	foreach (var row in nullableColumns)
	{
		Console.WriteLine($"ColumnName:{row["ColumnName"]}, DataType:{row["DataType"]}, AllowDBNull:{row["AllowDBNull"]}, ProviderType:{row["ProviderType"]}");
	}
}

I am getting NotSupportedException with the message "DataSet does not support System.Nullable<>" and the following stack trace:

   at System.Data.DataColumn..ctor(String columnName, Type dataType, String expr, MappingType type)
   at System.Data.Common.DataColumnMapping.CreateDataColumnBySchemaAction(String sourceColumn, String dataSetColumn, DataTable dataTable, Type dataType, MissingSchemaAction schemaAction)
   at System.Data.Common.DataColumnMapping.GetDataColumnBySchemaAction(String sourceColumn, String dataSetColumn, DataTable dataTable, Type dataType, MissingSchemaAction schemaAction)
   at System.Data.ProviderBase.SchemaMapping.SetupSchemaWithKeyInfo(MissingMappingAction mappingAction, MissingSchemaAction schemaAction, Boolean gettingData, DataColumn parentChapterColumn, Object chapterValue)
   at System.Data.ProviderBase.SchemaMapping..ctor(DataAdapter adapter, DataSet dataset, DataTable datatable, DataReaderContainer dataReader, Boolean keyInfo, SchemaType schemaType, String sourceTableName, Boolean gettingData, DataColumn parentChapterColumn, Object parentChapterValue)
   at System.Data.Common.DataAdapter.FillMappingInternal(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue)
   at System.Data.Common.DataAdapter.FillMapping(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue)
   at System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue)
   at System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
   at System.Data.DataTable.Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler)
   at UserQuery.Main(), line 14

The issue is that DataTable.Load incorrectly fills the data table column data types for nullable columns, i.e. it puts "Nullable`1[System.UInt64]". It should just put the base type there.

I attribute it to ClickHouse driver, as it does not occur with other drivers.

Expected Behavior

I would expect it to just properly fill the data table.

Steps To Reproduce

I used .NET 8
Installed ClickHouse.Client from NuGet
Used the code above.

Environment

- OS: Windows 10 x64
- Runtime: net8.0

Anything else?

No response

@Hermholtz Hermholtz added the bug Something isn't working label Oct 30, 2024
@DarkWanderer
Copy link
Owner

DarkWanderer commented Nov 7, 2024

Hi,

Can you try using ClickHouseDataAdapter?

        using var command = connection.CreateCommand();
        using var adapter = new ClickHouseDataAdapter();
        command.CommandText = sql;
        adapter.SelectCommand = command;
        var dataTable = new DataTable();
        adapter.Fill(dataTable);
        return dataTable;

Or, alternatively, ExecuteDataTable extension method which this library provides:

using ClickHouse.Client.Utility;

connection.ExecuteDataTable("SELECT * from system.tables");

@Hermholtz
Copy link
Author

Thank you for the workaround, it works the way you proposed, and the ExecuteDataTable is a great addition!
You certainly need to document that, otherwise it's hard to discover all the goodies you put there.

It doesn't resolve the issue, though. The issue I face (and I think many other could have this as well) is that we've got an existing C#/.NET-based reporting solution that works with pure ADO.NET object model. It allows to select the source of data (by selecting a driver and providing property values), transform and visualize data, similarly to what Power BI does, but it's a custom one. Therefore I do not have the ability to change its code. If I had it, I would perhaps make and exception for ClickHouse.

It would therefore be the best option if the ClickHouse.Client worked properly using the usual ADO.NET object model and typical code such as in my example above. That will certainly make the CH client more applicable. Thank you in advance for fixing this.

The simplest query that shows the issue is SELECT name, total_rows from system.tables as the total_rows is a nullable column.

@DarkWanderer
Copy link
Owner

Are you able to check if 7.8.3-aplha1 fixes your issue?

@Hermholtz
Copy link
Author

The 7.8.3-aplha1 version fixes the issue. I tried various data types:

string sql = "select toNullable(1), toNullable(1_000_000_000), toNullable(3.14), toNullable(now()), toNullable(True), toNullable('mystr')";

and it doesn't throw exception anymore.

Big THANK YOU for the fix! Hope you'll be able to release a non-alpha version soon!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants