我有一个名为getWords(int wrNum)
的函数,它使用实体框架从数据库返回wrNum数字随机数,当wrNum为300时,这个函数需要花费10秒的时间。我无法理解为什么需要这么多时间。请帮助我的代码出了什么问题?
public List<string> getWords(int wrNum)
{
IDVLTest d3 = new DVLTest();
for (int i = 0; i < wrNum;i++ )
{
string word = d3.getRandomWord().Text;
Words.Add(new WordView { Word = word, Status = WordStatus.Right });
}
return Words.Select(w=>w.Word).ToList();
}
public class DVLTest:IDVLTest
{
...
public Word getRandomWord()
{
Random r = new Random();
int i = r.Next(DVL_Entitie.Words.Count());
return DVL_Entitie.Words.ToList().ElementAt(i);
}
...
}
答案 0 :(得分:8)
因为您在每次迭代中都从数据库中检索整个列表,并且数据库访问通常很昂贵,因为它发生在进程外并且通常通过网络(数据库和应用程序/进程通常< / strong>不驻留在同一台服务器上)。您应该在for
循环之外检索一次列表,然后将检索到的列表作为参数传递给方法getRandomWord
。
DVL_Entitie.Words.Count() // offending line
DVL_Entitie.Words.ToList() // offending line
答案 1 :(得分:2)
正如@Igor所指出的
DVL_Entitie.Words.Count() // offending line
DVL_Entitie.Words.ToList() // offending line
数据库调用正在减慢这种速度你可以试试这个,因为它会缓存其余尝试的数量,并且一次只从数据库请求单个项目而不是整个数据库到列表然后选择所需的项目
public class DVLTest : IDVLTest
{
private int wordCount = -1;
public Word getRandomWord()
{
Random r = new Random();
int i = r.Next(this.getDBWordsCount());
return DVL_Entitie.Skip(i).Take(1);
}
private int getDBWordCount()
{
if(this.wordCount < 0)
{
this.wordCount = DVL_Entitie.Words.Count();
}
return this.wordCount;
}
}
答案 2 :(得分:1)
您可以执行以下操作,而不是将所有数据拉到内存中:
return DVL_Entitie.Words.Skip(i).Take(1).FirstOrDefault;
如果没有太多数据,Igor的解决方案似乎是最好的。
答案 3 :(得分:0)
谢谢大家。知道我的代码时间大约为0秒:D我喜欢你的想法@Gavin Harrison,我的代码现在是:
public List<string> getWords(int wrNum)
{
IDVLTest d3 = new DVLTest();
Random r = new Random();
for (int i = 0; i < wrNum;i++ )
{
string word = d3.getRandomWord(r).Text;
Words.Add(new WordView { Word = word, Status = WordStatus.Right });
}
return Words.Select(w=>w.Word).ToList();
}
public class DVLTest:IDVLTest
{
private int wordCount = -1;
private List<Word> DBWords;
public DVLTest()
{
DBWords = DVL_Entitie.Words.ToList();
}
public Word getRandomWord(Random r)
{
int i = r.Next(getDBWordCount());
return DBWords.ElementAt(i);
}
private int getDBWordCount()
{
if (this.wordCount < 0)
{
this.wordCount = DVL_Entitie.Words.Count();
}
return this.wordCount;
}
}