Fastest way to map result of SqlDataReader to object

后端 未结 11 1310
花落未央
花落未央 2021-02-04 08:49

I\'m comparing materialize time between Dapper and ADO.NET and Dapper. Ultimately, Dapper tend to faster than ADO.NET, though the first time a given fetch query was executed

11条回答
  •  我寻月下人不归
    2021-02-04 09:00

    Modified @HouseCat's solution to be case insensitive:

        /// 
        /// Maps a SqlDataReader record to an object. Ignoring case.
        /// 
        /// 
        /// 
        /// 
        /// https://stackoverflow.com/a/52918088
        public static void MapDataToObject(this SqlDataReader dataReader, T newObject)
        {
            if (newObject == null) throw new ArgumentNullException(nameof(newObject));
    
            // Fast Member Usage
            var objectMemberAccessor = TypeAccessor.Create(newObject.GetType());
            var propertiesHashSet =
                    objectMemberAccessor
                    .GetMembers()
                    .Select(mp => mp.Name)
                    .ToHashSet(StringComparer.InvariantCultureIgnoreCase);
    
            for (int i = 0; i < dataReader.FieldCount; i++)
            {
                var name = propertiesHashSet.FirstOrDefault(a => a.Equals(dataReader.GetName(i), StringComparison.InvariantCultureIgnoreCase));
                if (!String.IsNullOrEmpty(name))
                {
                    objectMemberAccessor[newObject, name]
                        = dataReader.IsDBNull(i) ? null : dataReader.GetValue(i);
                }
            }
        }
    

    EDIT: This does not work for List or multiple tables in the results.

    EDIT2: Changing the calling function to this works for lists. I am just going to return a list of objects no matter what and get the first index if I was expecting a single object. I haven't looked into multiple tables yet but I will.

        public async Task> ExecuteReaderAsync(string storedProcedureName, SqlParameter[] sqlParameters = null) where T : class, new()
        {
            var newListObject = new List();
            using (var conn = new SqlConnection(_connectionString))
            {
                conn.Open();
                SqlCommand sqlCommand = GetSqlCommand(conn, storedProcedureName, sqlParameters);
                using (var dataReader = await sqlCommand.ExecuteReaderAsync(CommandBehavior.Default))
                {
                    if (dataReader.HasRows)
                    {
                        while (await dataReader.ReadAsync())
                        {
                            var newObject = new T();
                            dataReader.MapDataToObject(newObject);
                            newListObject.Add(newObject);
                        }
                    }
                }
            }
            return newListObject;
        }
    

提交回复
热议问题