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

Microsoft.Data.Sqlite: Improve SqliteDataReader.GetSchemaTable() DataType when no rows #13839

Closed
Perksey opened this issue Jun 2, 2018 · 6 comments · Fixed by #14315
Closed
Assignees
Labels
area-adonet-sqlite closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Milestone

Comments

@Perksey
Copy link
Member

Perksey commented Jun 2, 2018

I'm using a custom DataAdapter i wrote to fill the void for the lack of one in this library, that is as follows:

using System;
using System.Data;
using System.Data.Common;
using Microsoft.Data.Sqlite;

namespace Ultz.BeagleFramework.SQLite
{
    public delegate void SqliteRowUpdatedEventHandler(Object sender, SqliteRowUpdatedEventArgs e);
    public delegate void SqliteRowUpdatingEventHandler(Object sender, SqliteRowUpdatingEventArgs e);
    public sealed class SqliteDataAdapter : DbDataAdapter
    {
        public event SqliteRowUpdatedEventHandler RowUpdated;

        public event SqliteRowUpdatingEventHandler RowUpdating;

        public SqliteDataAdapter() { }

        public SqliteDataAdapter(SqliteCommand selectCommand)
        {
            SelectCommand = selectCommand;
        }

        public SqliteDataAdapter(string selectCommandText, SqliteConnection selectConnection)
            : this(new SqliteCommand(selectCommandText, selectConnection)) { }

        public SqliteDataAdapter(string selectCommandText, string selectConnectionString)
            : this(selectCommandText, new SqliteConnection(selectConnectionString)) { }

        protected override RowUpdatedEventArgs CreateRowUpdatedEvent( DataRow dataRow,  IDbCommand command,
                                                                     System.Data.StatementType statementType,
                                                                      DataTableMapping tableMapping)
        {
            return new SqliteRowUpdatedEventArgs(dataRow, command, statementType, tableMapping);
        }

        protected override RowUpdatingEventArgs CreateRowUpdatingEvent( DataRow dataRow,  IDbCommand command,
                                                                       System.Data.StatementType statementType,
                                                                        DataTableMapping tableMapping)
        {
            return new SqliteRowUpdatingEventArgs(dataRow, command, statementType, tableMapping);
        }

        protected override void OnRowUpdated( RowUpdatedEventArgs value)
        {
            //base.OnRowUpdated(value);
            if (RowUpdated != null && value is SqliteRowUpdatedEventArgs)
                RowUpdated(this, (SqliteRowUpdatedEventArgs)value);
        }

        protected override void OnRowUpdating( RowUpdatingEventArgs value)
        {
            if (RowUpdating != null && value is SqliteRowUpdatingEventArgs)
                RowUpdating(this, (SqliteRowUpdatingEventArgs)value);
        }

        public new SqliteCommand DeleteCommand
        {
            get { return (SqliteCommand)base.DeleteCommand; }
            set { base.DeleteCommand = value; }
        }

        public new SqliteCommand SelectCommand
        {
            get { return (SqliteCommand)base.SelectCommand; }
            set { base.SelectCommand = value; }
        }

        public new SqliteCommand UpdateCommand
        {
            get { return (SqliteCommand)base.UpdateCommand; }
            set { base.UpdateCommand = value; }
        }

        public new SqliteCommand InsertCommand
        {
            get { return (SqliteCommand)base.InsertCommand; }
            set { base.InsertCommand = value; }
        }
    }

#pragma warning disable 1591

    public class SqliteRowUpdatingEventArgs : RowUpdatingEventArgs
    {
        public SqliteRowUpdatingEventArgs(DataRow dataRow, IDbCommand command, System.Data.StatementType statementType,
                                          DataTableMapping tableMapping)
            : base(dataRow, command, statementType, tableMapping) { }
    }

    public class SqliteRowUpdatedEventArgs : RowUpdatedEventArgs
    {
        public SqliteRowUpdatedEventArgs(DataRow dataRow, IDbCommand command, System.Data.StatementType statementType,
                                         DataTableMapping tableMapping)
            : base(dataRow, command, statementType, tableMapping) { }
    }

#pragma warning restore 1591
}

After creating a table, I then SELECT * FROM the table, and use SqliteDataAdapter.Fill(). However, all of the types are set to Int32. This also happens when using DataTable.Load().

@Perksey
Copy link
Member Author

Perksey commented Jun 3, 2018

It's worth noting that this only happens to empty tables. If I manually correct the types, and add data to the DataTable, SELECT * FROM the table works perfectly fine.

@bricelam
Copy link
Contributor

bricelam commented Jun 4, 2018

Related to #435. This happens because columns don't have static types in SQLite. It uses a dynamic type system. The type comes from each field, not the column definition. At its worst, this means each row could actually have a different type.

@bricelam
Copy link
Contributor

bricelam commented Jun 4, 2018

We should apply the same decision for #435 to SqliteDataReader.GetSchemaTable() when there are no rows.

@bricelam
Copy link
Contributor

bricelam commented Jun 4, 2018

(I'm leaning toward using the column's type affinity at this point.)

@bricelam bricelam changed the title Empty table loaded into DataTable with incorrect types Improve SqliteDataReader.GetSchemaTable() when no rows Jun 4, 2018
@bricelam bricelam changed the title Improve SqliteDataReader.GetSchemaTable() when no rows Improve SqliteDataReader.GetSchemaTable() DataType when no rows Jun 4, 2018
@bricelam bricelam self-assigned this Jun 6, 2018
@ajcvickers ajcvickers transferred this issue from aspnet/Microsoft.Data.Sqlite Oct 31, 2018
@ajcvickers ajcvickers added this to the 3.0.0 milestone Oct 31, 2018
@ajcvickers ajcvickers changed the title Improve SqliteDataReader.GetSchemaTable() DataType when no rows Microsoft.Data.Sqlite: Improve SqliteDataReader.GetSchemaTable() DataType when no rows Oct 31, 2018
@bricelam bricelam added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Mar 25, 2019
@ajcvickers ajcvickers modified the milestones: 3.0.0, 3.0.0-preview7 Jul 2, 2019
@ajcvickers ajcvickers modified the milestones: 3.0.0-preview7, 3.0.0 Nov 11, 2019
@JensNordenbro
Copy link

@Perksey, what license is the code you posted under?

@Perksey
Copy link
Member Author

Perksey commented Oct 5, 2020

MIT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-adonet-sqlite closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants