List<T> overwrites all the items inside a foreach loop to the last value

为君一笑 提交于 2019-12-02 11:56:31

问题


I'm trying to build a windows application in which there is a combo box and during the Load(), I'm population this combo box with all the connection strings availabe in my app.Config file.

Here is the app.Config snippet:

<!-- Adding Multiple Servers in Connection String-->
<connectionStrings>
   <add name="SQLConnect-1"
         connectionString="Data Source=SAHIL; Initial Catalog=RecordComparisonTool; Integrated Security=SSPI"
         providerName="System.Data.SqlCLient"/>

   <add name="SQLConnect-2"
     connectionString="Data Source=SAHIL; Initial Catalog=RecordComparisonTool; User Id=test; Password=12123; Integrated Security=SSPI"
     providerName="System.Data.SqlCLient"/>

   <add name="SQLConnect-3"
     connectionString="Data Source=SAHIL; Initial Catalog=RecordComparisonTool; User Id=test; Password=32315;  Integrated Security=True"
     providerName="System.Data.SqlCLient"/>
 </connectionStrings>

I have created a class CompareResult in which I'm trying to get all the values from the app.Config and displaying it to the combo box.

namespace RecordComparisonTool_Win
{
   public class ConnectionString
   {
        public string name { get; set; }
        public string conString { get; set; }
        public string provider { get; set; }
    }

    public class CompareResult
    {

        public List<ConnectionString> GetConnection()
        {
            List<ConnectionString> conStr = new List<ConnectionString>();
            ConnectionString conn = new ConnectionString();

            foreach (ConnectionStringSettings css in ConfigurationManager.ConnectionStrings)
            {
                if (!(css.Name == "LocalSqlServer" || css.Name == "LocalMySqlServer"))
                {
                    conn.name = css.Name;
                    conn.conString = css.ConnectionString;
                    conn.provider = css.ProviderName;

                    conStr.Add(conn);
                }
            }
            return conStr;
        }

    }
}

The problem is when I'm trying to bind it with the Combo box, it is showing three records as per the app.Config file, but all the records have same value as "SQLConnect-3". I'm unable to find the reason why the List got updated with "SQLConnect-3" for all the records. Please help to fix the error. Here is the snippet where I'm binding this list to ComboBox

protected void LoadConnection()
{
    CompareResult compareResult = new CompareResult();

    List<ConnectionString> connectionString = new List<ConnectionString>();
    connectionString = compareResult.GetConnection();

    cbTokenLeft.DataSource = connectionString;

    cbTokenLeft.DisplayMember = "name";
    cbTokenLeft.ValueMember = "conString";

}

回答1:


This:

conn.name = css.Name;
conn.conString = css.ConnectionString;
conn.provider = css.ProviderName;

conStr.Add(conn);

Overwrites your ConnectionString reference each iteration. You need to allocate a new ConnectionString within each loop:

foreach (ConnectionStringSettings css in ConfigurationManager.ConnectionStrings)
{
    if (!(css.Name == "LocalSqlServer" || css.Name == "LocalMySqlServer"))
    {
        var conn = new ConnectionString
        {
           name = css.Name;
           conString = css.ConnectionString;
           provider = css.ProviderName;
        }
        conStr.Add(conn);
    }
}



回答2:


Move the line ConnectionString conn = new ConnectionString(); inside the innermost loop. It's a reference class, and you are adding the same instance to your list over and over.

    public List<ConnectionString> GetConnection()
    {
        List<ConnectionString> conStr = new List<ConnectionString>();

        foreach (ConnectionStringSettings css in ConfigurationManager.ConnectionStrings)
        {
            if (!(css.Name == "LocalSqlServer" || css.Name == "LocalMySqlServer"))
            {
                ConnectionString conn = new ConnectionString();
                conn.name = css.Name;
                conn.conString = css.ConnectionString;
                conn.provider = css.ProviderName;

                conStr.Add(conn);
            }
        }
        return conStr;
    }



回答3:


Since you're instantiating your ConnectionString outside your loop, the same instance is used (and overwritten) for all iterations. You need to instantiate it within your loop, so that each iteration gets a new instance:

foreach (ConnectionStringSettings css in ConfigurationManager.ConnectionStrings)
{
    if (!(css.Name == "LocalSqlServer" || css.Name == "LocalMySqlServer"))
    {
        ConnectionString conn = new ConnectionString();

        conn.name = css.Name;
        conn.conString = css.ConnectionString;
        conn.provider = css.ProviderName;

        conStr.Add(conn);
    }
}

You can also express the same code using LINQ:

var conStr = 
(
    from css in ConfigurationManager.ConnectionStrings
    where !(css.Name == "LocalSqlServer" || css.Name == "LocalMySqlServer")
    select new ConnectionString
    {
        name = css.Name,
        conString = css.ConnectionString,
        provider = css.ProviderName,
    }
).ToList();


来源:https://stackoverflow.com/questions/29875452/listt-overwrites-all-the-items-inside-a-foreach-loop-to-the-last-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!