简体   繁体   English

字符串构建器的用途是什么?

[英]What is the purpose of the string builder here?

I've only done C++ and some C# and I am new to MySQL and I don't understand the purpose of the string builder here. 我只做了C ++和一些C#,我是MySQL新手,我不明白字符串构建器的用途。

This code is part of a program which is used to extract data from a webpage and insert it into an already existing Word File using bookmarks. 此代码是程序的一部分,该程序用于从网页中提取数据并使用书签将其插入到现有的Word文件中。

MY CODE 我的代码

using System.Collections.Generic;
using System.Configuration;
using System.Text;
using MySql.Data.MySqlClient;

namespace ARExtractionLibrary
{
    public class DataExtractor
    {
        #region Attributes
        private string _databaseConfig = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
        private const int AR_TRACKER_ID = 10;
        private const int AR_NUMBER_ID = 3;
        #endregion

        #region Methods
        public Dictionary<string, Field> GetFieldData(int TicketID)
        {
            MySqlConnection sqlConnection = new MySqlConnection(_databaseConfig);
            Dictionary<string, Field> fieldsDictionary = new Dictionary<string, Field>();

            StringBuilder queryDefaultFields = new StringBuilder();
            queryDefaultFields.Append("SELECT issues.id AS TicketID, issues.subject, issues.description, ");
            queryDefaultFields.Append(" CONCAT(users.firstname,' ', users.lastname) as Author");
            queryDefaultFields.Append(" FROM issues LEFT JOIN users ON users.id =issues.author_id");
            queryDefaultFields.Append("  WHERE issues.id = @TicketID");

            StringBuilder queryCustomFields = new StringBuilder();
            queryCustomFields.Append("SELECT custom_fields.name, custom_fields.field_format, CONCAT(users.firstname,' ',users.lastname) AS value");
            queryCustomFields.Append(" FROM custom_values");
            queryCustomFields.Append(" LEFT JOIN custom_fields ON custom_values.custom_field_id = custom_fields.id");
            queryCustomFields.Append(" JOIN users ON custom_values.value = users.id");
            queryCustomFields.Append(" WHERE custom_values.customized_id = @TicketId");
            queryCustomFields.Append(" AND field_format = 'user'");
            queryCustomFields.Append(" UNION");
            queryCustomFields.Append(" SELECT custom_fields.name, custom_fields.field_format, custom_values.value");
            queryCustomFields.Append(" FROM custom_values");
            queryCustomFields.Append(" LEFT JOIN custom_fields ON custom_values.custom_field_id = custom_fields.id");
            queryCustomFields.Append(" WHERE custom_values.customized_id = @TicketId");
            queryCustomFields.Append(" AND field_format <> 'user'");

            sqlConnection.Open();

            //First query
            MySqlCommand sqlCommand = null;
            sqlCommand = new MySqlCommand(queryDefaultFields.ToString(), sqlConnection);
            sqlCommand.Parameters.AddWithValue("@TicketId", TicketID);

            MySqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
            while (sqlDataReader.Read())
            {
                Field subject = new Field("Subject", sqlDataReader["subject"].ToString());
                fieldsDictionary.Add(subject.Name, subject);

                Field description = new Field("Description", sqlDataReader["description"].ToString());
                fieldsDictionary.Add(description.Name, description);

                Field ticketID = new Field("TicketID", sqlDataReader["TicketID"].ToString());
                fieldsDictionary.Add(ticketID.Name, ticketID);

                Field author = new Field("Author", sqlDataReader["Author"].ToString());
                fieldsDictionary.Add(author.Name, author);
            }
            sqlDataReader.Close();

            //Second query
            sqlCommand = new MySqlCommand(queryCustomFields.ToString(), sqlConnection);
            sqlCommand.Parameters.AddWithValue("@TicketId", TicketID);
            sqlDataReader = sqlCommand.ExecuteReader();

            while (sqlDataReader.Read())
            {
                string fieldName = sqlDataReader["name"].ToString();
                string fieldValue = sqlDataReader["value"].ToString();
                string fieldFormat = sqlDataReader["field_format"].ToString();

                if (fieldsDictionary.ContainsKey(fieldName))
                {
                    fieldsDictionary[fieldName].Values.Add(fieldValue);
                }

                else
                {
                    Field localField = new Field(fieldName, fieldValue, fieldFormat);
                    fieldsDictionary.Add(localField.Name, localField);
                }
            }
            sqlDataReader.Close();
            sqlConnection.Close();

            return fieldsDictionary;
        }

        public Dictionary<int, string> GetARs()
        {
            Dictionary<int, string> ARDictionary = new Dictionary<int, string>();
            MySqlConnection sqlConnection = new MySqlConnection(_databaseConfig);
            StringBuilder sqlCommandIsAR = new StringBuilder();
            sqlCommandIsAR.Append("SELECT issues.id AS TicketID, issues.tracker_id AS Tracker, issues.subject AS Subject, custom_values.custom_field_id, custom_values.value");
            sqlCommandIsAR.Append(" FROM issues LEFT JOIN Custom_values ON custom_values.customized_id = issues.id ");
            sqlCommandIsAR.Append(" WHERE tracker_id = @IsAR AND custom_field_id = @IsARNumber ");

            sqlConnection.Open();

            MySqlCommand commandGetARs = new MySqlCommand(sqlCommandIsAR.ToString(), sqlConnection);
            commandGetARs.Parameters.AddWithValue("@IsAR", AR_TRACKER_ID);
            commandGetARs.Parameters.AddWithValue("@IsARNumber", AR_NUMBER_ID);
            MySqlDataReader sqlDataReader = null;
            sqlDataReader = commandGetARs.ExecuteReader();

            while (sqlDataReader.Read())
            {
                string DictionaryValue = sqlDataReader["TicketID"].ToString() + " - " + sqlDataReader["Subject"].ToString();

                if (sqlDataReader["value"].ToString().Length != 0)
                {
                    DictionaryValue += " [" + sqlDataReader["value"].ToString() + "]";
                }

                int key = int.Parse(sqlDataReader["TicketID"].ToString());
                ARDictionary.Add(key, DictionaryValue);
            }

            sqlDataReader.Close();
            sqlConnection.Close();

            return ARDictionary;
        }

        #endregion
    }
}

StringBuilder prevents having to recreate a string each time you are adding to it. StringBuilder可防止每次添加字符串时都重新创建字符串。 Using the String class in C# means you are using an immutable object, but StringBuilder is much faster in most cases since it's not having to create a new String each time you append to it. 在C#中使用String类意味着您使用的是不可变对象,但StringBuilder在大多数情况下要快得多,因为每次附加时都不必创建新的String。

So in general, if you are appending to a String many times, StringBuilder will be more efficient than just doing str += "text to append" (where str is a String ). 所以一般来说,如果你多次附加一个String, StringBuilder将比仅仅执行str += "text to append" (其中str是一个String )更有效。

There are some caveats to be aware of here though, please refer to this answer. 这里有一些需要注意的注意事项,请参考这个答案。

In general 一般来说

A StringBuilder allows you to build up a string without reallocating a buffer for the string's contents on every mutating operation (the same buffer is used throughout; it is only reallocated when the string expands beyond the current capacity). StringBuilder允许您构建一个字符串,而无需在每次变异操作时为字符串的内容重新分配缓冲区(整个过程使用相同的缓冲区;只有在字符串扩展超出当前容量时才会重新分配)。 This makes the whole process of building up a big string much more performant. 这使得构建大字符串的整个过程更加高效。

In this code 在这段代码中

In this case there is no dynamic building up of a string at all; 在这种情况下,根本没有动态构建字符串; the strings are practically hardcoded. 字符串实际上是硬编码的。 Here StringBuilder is totally pointless; 这里的StringBuilder完全没有意义; it would actually be better for performance if the strings were hardcoded literals like this: 如果字符串是这样的硬编码文字,它实际上会更好的表现:

var queryDefaultFields = @"SELECT issues.id AS TicketID, issues.subject, issues.description,
                           CONCAT(users.firstname,' ', users.lastname) as Author
                           FROM issues LEFT JOIN users ON users.id =issues.author_id
                           WHERE issues.id = @TicketID";

My guess is that the author of this code either misused StringBuilder because they remembered reading that "it's faster this way" but never really understood why, or else is guilty of negligent copy-pasting. 我的猜测是这段代码的作者误用了StringBuilder因为他们记得读过“这种方式更快”,但从来没有真正理解为什么,或者是因为疏忽的复制粘贴而犯了罪。

To increase performance, as you are going to do a lot of addition of strings. 为了提高性能,您将要添加很多字符串。 It's well known that even being reference type string behaves like value type. 众所周知,即使是引用类型string表现得像value类型。

So on every addition of the string a new string object is allocated. 因此,在每次添加字符串时,都会分配一个新的字符串对象。

string s = "hello"; 
s += " world"; //NEW STRING OBJECT ALLOCATED 

In case of the StringBuilder , instead, there is not any new allocation, but just appending to the end of it. 相反,在StringBuilder情况下,没有任何新的分配,只是附加到它的末尾。

StringBuilder queryDefaultFields = new StringBuilder();
queryDefaultFields.Append("hello");   //THE SAME queryDefaultFields OBJECT
queryDefaultFields.Append(" world");  //THE SAME queryDefaultFields OBJECT

由于StringBuilder是可变的(相反作为字符串),这意味着您可以在任何给定时间使用Append(或AppendLine)方法向其添加数据。只要您有它的引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM