Quelle est la meilleure façon de sérialiser rapidement un DataReader sans utiliser DataTable (ou en utilisant un DataTable qui pourrait avoir des noms de colonnes en double)

dapper datareader datatable

Question

Nous stockons largement nos requêtes en utilisant un décorateur qui encapsule IDbConnection / IDbCommand. Lorsque quelque chose appelle «ExecuteReader ()», elle utilise la commande command.text comme clé de cache (par exemple, SELECT * FROM Foo ) et nous pouvons également appliquer des balises à nos décorateurs (par exemple, new FooDbCommand("UserCacheTag") ) . Le Reader est converti en un DataTable pour être facilement sérialisable et reconverti à l'aide de l'api DataTables (CreateDataReader).

Tout cela fonctionne avec brio, mais il y a un défaut.

Si le jeu d'enregistrements entrant a des noms de colonnes en double, à mesure que le lecteur IDataReader est traduit en un DataTable, les noms de colonnes en double sont incrémentés d'un nombre (par exemple, 'PersonID1').

Comment pouvons-nous créer notre IDataReader, qui autorise les noms de colonnes en double, pouvant être mis en cache (de préférence sérialisables), puis le reconvertir en IDataReader avec les noms de colonnes d'origine sans craindre que les noms de colonnes soient modifiés entre les états?

Information additionnelle:

Nous utilisons principalement Dapper avec le type de retour dynamique pour éviter ces problèmes. Nous aimerions commencer à utiliser davantage le multimapping. Mais si un type, par exemple "Personne", est renvoyé plusieurs fois dans une requête, des noms de colonnes en double apparaissent.

Par exemple:

SELECT pEmployee.*, pManager.* 
FROM Persons pEmployee 
LEFT OUTER JOIN Persons pManager ON pManager.PersonID = pEmployee.ManagerPersonID

Réponse populaire

J'ai accompli cela en créant ma propre classe DataTable qui stocke le nom de colonne d'origine dans la propriété 'Caption' et mon propre IDataReader qui remplace la méthode GetName () pour rechercher la table de schéma. C'est assez simple, mais j'aimerais bien qu'un DataTable contienne simplement une propriété 'AllowDuplicateColumnNames'.

MyDataTable

Lors du chargement du DataReader, la propriété 'Caption' sera affectée au nom de la colonne d'origine. Lors de la création du DataReader, la propriété 'ColumnName' du schéma peut être renommée en son nom d'origine (actuellement stocké dans la colonne Légende).

internal class MyDataTable : DataTable
    {
        public MyDataTable()
        {

        }

        /// <summary>
        /// This is a helper method which accounts for duplicate column names.
        /// In the loading process, it will rewrite the caption to be the original column name
        /// which can be a duplicate.
        /// </summary>
        /// <param name="dataReader"></param>
        public void LoadIDataReader(IDataReader dataReader)
        {
            var schemaTable = dataReader.GetSchemaTable();

            base.Load(dataReader);

            for (var i = 0; i < schemaTable.Rows.Count; i++)
            {
                var originalColumnName = schemaTable.Rows[i]["ColumnName"] as string;
                var currentColumnName = this.Columns[i].ColumnName;

                if(originalColumnName != currentColumnName)
                {
                    this.Columns[i].Caption = originalColumnName;
                }
            }
        }

        public IDataReader CreateIDataReader()
        {
            var dataReader = base.CreateDataReader();

            var schemaTable = dataReader.GetSchemaTable();

            for(var i = 0; i < schemaTable.Rows.Count; i++)
            {
                //this is reverse from above
                var originalColumnName = this.Columns[i].Caption;
                var currentColumnName = schemaTable.Rows[i]["ColumnName"] as string;

                if (originalColumnName != currentColumnName)
                {
                    schemaTable.Rows[i]["ColumnName"] = originalColumnName;
                }
            }

            return new MyDataReader(dataReader);
        }
    }

MyDataReader: IDataReader

Cela accepte un datareader et agit simplement comme un décorateur pour la méthode GetName ().

internal class MyDataReader : IDataReader
    {
        private IDataReader _dataReader;

        public MyDataReader(IDataReader dataReader)
        {
            _dataReader = dataReader;
        }

        //other IDataReader methods not included for clarity

        public string GetName(int i)
        {
            return this.GetSchemaTable().Rows[i]["ColumnName"] as string;
        }
    }


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi