简体   繁体   中英

c# dictionary select value from key

I've been searching through here and I realize that similar questions have been asked before, and I've gone over several, but what seems to be correct doesn't seem to be working for.

I have the following method which pulls a set of key value pairs in a DataSet gathered from a SQL query.

    public static Dictionary<string, string> LoadConfiguration()
    {
        DataSet sqlResults = data.GetSettings();

        Dictionary<string, string> dict = 
            new Dictionary<String, String>();

        foreach (DataRow dr in sqlResults.Tables[0].Rows)
        {
            dict.Add(
                dr.Field<string>("key"), dr.Field<string>("value")
                    );
        }

        return dict;
    }

It's as simple as it gets as far as I can see, but I've never actually worked with a dictionary before as I'm relatively new to any kind of real programming.

I know that my Dictionary has the expected data, because if I iterate through it with a foreach, it gives me the expected results

    foreach (KeyValuePair<string, string> i in MyStuff.Configuration.LoadConfiguration())
    {
        Console.WriteLine("Key = " + i.Key + " Value = " + i.Value);
    }

which gives me the following which is all I've implemented so far

Key = EnableLdap Value = false Key = LdapPath Value = LDAP://DC=some,DC=domain,DC=com Key = SessionTimeout Value = 60

But I only want to select a specific value from a key named EnableLdap for example

My understanding is that both the following methods would be correct. But when I try this way, I get a KeyNotFoundException

    Dictionary<string,string> dict = MyStuff.Configuration.LoadConfiguration();
    Console.WriteLine(dict["EnableLdap"]);

If I try this I get a [InvalidOperationException: Sequence contains no matching element]

    Dictionary<string,string> dict = MyStuff.Configuration.LoadConfiguration();
    Console.WriteLine(dict.Single(s => s.Key == "EnableLdap").Value);

And if I try this I just get nothing

    string value = "";

    if (dict.TryGetValue("EnableLdap", out value))
    {
        dict["EnableLdap"] = value;
        Console.WriteLine(value);

    }

I'm pretty certain I'm missing something simple here and the answer will result in a facepalm

SOLUTION:

I got caught by trailing spaces as was suggested a few times in the comments. The solution was to simply add some trimming to my row values when adding them to my Dictionary.

public static Dictionary<string, string> LoadConfiguration()
{
    DataSet sqlResults = data.GetSettings();

    Dictionary<string, string> dict = 
        new Dictionary<String, String>();

    foreach (DataRow dr in sqlResults.Tables[0].Rows)
    {
        dict.Add(
            dr.Field<string>("key").Trim(), dr.Field<string>("value").Trim()
                );
    }

    return dict;
}

It is one of these 2 issues.

  1. The key does not exist in the dictionary, this could be due to a spelling mistake or even a leading/trailing space or something of that nature.
  2. The key exists but is cased differently than you think it is.

For option 2 you can ensure that casing is not an issue by providing a StringComparer to the dictionary as an argument in the constructor.

Dictionary<string, string> dict = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);

The above code snippet will ensure that the dictionary creates the hash for each key based on the ordinal case insensitive representation of the string key. This will allow for the following example to pass:

dict["enableldap"] = "true";
Console.WriteLine(dict["EnableLdap"]);

See StringComparer for more options.

My understanding is that both the following methods would be correct. But when I try this way, I get a KeyNotFoundException

It seems that your dictionary doesn't have that key. Keep in mind that dictionaries are key-sensitive you can check if a key exist by using this method:

Console.WriteLine("Exist key "+ dict.ContainsKey("EnableLdap"));

If I try this I get a [InvalidOperationException: Sequence contains no matching element]

  Dictionary<string,string> dict = MyStuff.Configuration.LoadConfiguration();
    Console.WriteLine(dict.Single(s => s.Key == "EnableLdap").Value);

The linQ method .Single expects to find a value. If no value is found that Exception will be thrown. You should be using .SingleOrDefault if you don't want that exception, but beware of nulls.

And if I try this I just get nothing .

TryGetValue doesn't throw any exceptions. It just tries.

I'd suggest you to add a format for your keys either uppercased or lowercased, when you're creating the dictionary.

foreach (DataRow dr in sqlResults.Tables[0].Rows)
        {
            dict.Add(
                dr.Field<string>("key").ToUpperCase(), dr.Field<string>("value")
                    );
        }

and then you can query it like this:

if(dict.ContainsKey("ENABLELDAP"))
{
   string value = dict["ENABLELDAP"];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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