【问题标题】:How to store database values in dictionary in C#如何在 C# 中将数据库值存储在字典中
【发布时间】:2019-04-01 21:54:10
【问题描述】:

当我收到一个国家名称时,我想在我的数据库中搜索一个国家名称列表并获取与国家名称相关联的 id。目前我有;

    public static int GetCountryId(string countryName)
    {
        int countryId = 0;
        if (!string.IsNullOrEmpty(countryName))
        {
            var listOfCountries = GetCountries();
            var match = listOfCountries.FirstOrDefault(item => (item.Name).Contains(countryName));
            if (match != null)
            {
                countryId = match.Id;
            }
        }
        return countryId;
    }

    private static List<Country> GetCountries()
    {
        string query = $"SELECT Id, Name FROM Countries";
        List<Country> cases = Common.GetCollection<Country>(Properties.Settings.Default.DbConnectionString, query);
        return cases;
    }

但是,如您所见,每次我想获取国家名称列表时都必须查询数据库。我想拥有它,以便将此列表存储在字典中,而我可以访问字典。

有谁知道我可以如何改进我的代码,这样我就不必每次都访问数据库了?

【问题讨论】:

    标签: c# sql database


    【解决方案1】:

    像这样修改你的方法:

    private static List<Country> countries;
    
    private static List<Country> GetCountries()
    {
        if (countries == null || countries.Count == 0)
        {
            string query = $"SELECT Id, Name FROM Countries";
            countries = Common.GetCollection<Country>(Properties.Settings.Default.DbConnectionString, query);
        }
    
        return countries;
    }
    

    【讨论】:

      【解决方案2】:

      当你的程序第一次启动时,如何创建一个静态构造函数来填充一个国家 ID 的字典,这样你只需要查询一次数据库。那么调用 GetCountryId 就可以使用那个字典了吗?

      private static Dictionary<string, int> CountryIds;
      
      public static NameOfYourClass(){
          CountryIds = new Dictionary<string, int>();
          string query = $"SELECT Id, Name FROM Countries";
          List<Country> cases = Common.GetCollection<Country>(Properties.Settings.Default.DbConnectionString, query);
          foreach (country Country in cases)
          {
              CountryIDs.Add(Country.Name, Country.Id);
          }        
      }
      
      public static int GetCountryId(string countryName)
      {
          if(!CountryIds.Contains(countryName) return 0;
          return CountryIds[countryName];
      }
      

      【讨论】:

        【解决方案3】:

        让我们为此做一个延迟加载!

        private Dictionary<string, Country> _countryNames = null;
        
        public Dictionary<string, Country> CountryNames
        {
            get
            {
                 if(_countryNames == null)
                 {
                     _countryNames = new Dictionary<int, Country>();
                     foreach(var country in GetCountries())
                     {
                         _countryNames.Add(country.Name, country)
                     }
                 }
                 return _countryNames;
            }
        }
        
        public static int GetCountryId(string countryName)
        {
            Country result;
            CountryNames.TryGetValue(countryName, out result);
            if (result == null) return 0;
            return result.Id;
        }
        
        private static IEnumerable<Country> GetCountries()
        {
            string query = "SELECT Id, Name FROM Countries";
            return Common.GetCollection<Country>(Properties.Settings.Default.DbConnectionString, query);
        }
        

        但通常让数据库做这件事会更好:根据需要在那里运行查询,将过滤器字符串传递给数据库。不幸的是,Common.GetCollection&lt;T&gt;() 对我们隐藏了这种能力。 query 变量应如下所示:

        string query = "SELECT Id, Name FROM Countries WHERE Name = @CountryName";
        

        但从这里的问题中不清楚如何提供@CountryName 参数值。您应该 做的是使用字符串替换或插值将值直接包含在查询字符串中。那将是非常糟糕;它创建了一种称为 SQL 注入的严重形式的安全问题。

        【讨论】:

        • 感谢您的详细回复!不过,我很好奇您对字符串替换的意思。如果我给了@CountryName 参数,这怎么可能是安全威胁?听说过 SQL 注入,但不知道它是如何应用于这种情况的?
        • 为什么不跟Lazy&lt;&gt;一行呢?
        • 如果您只是对@CountryName 值进行字符串替换,您将很容易受到攻击。参数化查询将参数数据与 sql 命令字符串分开发送到数据库服务器。但是您必须以某种方式告诉应用程序有关参数的信息。
        【解决方案4】:

        你可能有一个这样的公共字典:

        public static Dictionary<int, string> countries = new Dictionary<int, string>();
        

        如果之前没有填充,该方法将填充字典;

        private static void GetCountries()
            {
                if(countries.Count == 0)
                {
                      string query = $"SELECT Id, Name FROM Countries";
                      countries = Common.GetCollection<Country>(Properties.Settings.Default.DbConnectionString, query)
                      .ToDictionary(x => x.Id, x=> x.Name);
                }
            }
        
        
        public static int GetCountryId(string countryName)
        {
            return countries.Contains(countryName) CountryIds[countryName] : 0;
        }
        

        【讨论】:

        • 无法从静态方法访问非静态成员。
        • 再次检查答案。我修好了。
        • 你知道GetCountryId 方法会如何改变吗?
        • @user180708 我刚刚编辑了我的答案。请看一看。
        猜你喜欢
        • 2011-02-22
        • 1970-01-01
        • 2011-02-13
        • 2011-01-19
        • 2020-01-26
        • 2011-05-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多