对从数据库获取的模型对象进行缓慢的C#迭代
我试图从数据库中获取业务模型实体,然后迭代它们以搜索字符串。但是,在我的localhost中,对于500个对象,此操作大约需要7到9秒对从数据库获取的模型对象进行缓慢的C#迭代,c#,linq,entity-framework,foreach,C#,Linq,Entity Framework,Foreach,我试图从数据库中获取业务模型实体,然后迭代它们以搜索字符串。但是,在我的localhost中,对于500个对象,此操作大约需要7到9秒 public List<FileFolder> SearchFolders(int id, string searchString) { /* Placeholder that references folders that passes search criteria */ List<FileFolder> added
public List<FileFolder> SearchFolders(int id, string searchString)
{
/* Placeholder that references folders that passes search criteria */
List<FileFolder> addedFolders = new List<FileFolder>();
/* Get the folder with specified id, also include Folders
* that this folder has. No problem here works perfectly fine
* and fast */
FileFolder folder = dbSet.Include("Folders").
.Where(q => q.FileFolderID == id)
.ToList().FirstOrDefault();
/* This takes too much time as I mention, up to 9 seconds
* for 500 Folders */
foreach (FileFolder f in folder.Folders)
{
if (f.Name.Contains(searchString))
{
addedFolders.Add(f);
}
}
return addedFolders;
}
公共列表搜索文件夹(int-id,string-searchString)
{
/*引用通过搜索条件的文件夹的占位符*/
List addedFolders=新列表();
/*获取具有指定id的文件夹,还包括文件夹
*这个文件夹有。这里没有问题,工作很好
*而且很快*/
filefolderfolder=dbSet.Include(“文件夹”)。
.Where(q=>q.FileFolderID==id)
.ToList().FirstOrDefault();
/*正如我提到的,这需要花费太多的时间,最多9秒
*用于500个文件夹*/
foreach(文件夹.Folders中的文件文件夹f)
{
if(f.Name.Contains(searchString))
{
添加文件夹。添加(f);
}
}
返回addedFolders;
}
我正在将提取的数据转换为列表,以便可以安全地说所有数据现在都在内存中?因此,在访问文件夹时,foreach循环不应再进行任何db调用。我还检查了.Include
方法,它工作正常
这一缓慢迭代的原因可能是什么
谢谢。试着用这个代替Foreach:
if (folder!=null)
{
addedFolders.AddRange(folder.Folders.Where(f=>f.Name.Contains(searchString)));
}
完整代码如下所示:
public List<FileFolder> SearchFolders(int id, string searchString)
{
/* Placeholder that references folders that passes search criteria */
List<FileFolder> addedFolders = new List<FileFolder>();
/* Get the folder with specified id, also include Folders
* that this folder has. No problem here works perfectly fine
* and fast */
FileFolder folder = dbSet.Include("Folders").
.Where(q => q.FileFolderID == id)
.FirstOrDefault();
if (folder!=null)
{
addedFolders.AddRange(folder.Folders.Where(f=>f.Name.Contains(searchString)));
}
return addedFolders;
}
公共列表搜索文件夹(int-id,string-searchString)
{
/*引用通过搜索条件的文件夹的占位符*/
List addedFolders=新列表();
/*获取具有指定id的文件夹,还包括文件夹
*这个文件夹有。这里没有问题,工作很好
*而且很快*/
filefolderfolder=dbSet.Include(“文件夹”)。
.Where(q=>q.FileFolderID==id)
.FirstOrDefault();
如果(文件夹!=null)
{
addedFolders.AddRange(folder.Folders.Where(f=>f.Name.Contains(searchString));
}
返回addedFolders;
}
试着用这个代替Foreach:
if (folder!=null)
{
addedFolders.AddRange(folder.Folders.Where(f=>f.Name.Contains(searchString)));
}
完整代码如下所示:
public List<FileFolder> SearchFolders(int id, string searchString)
{
/* Placeholder that references folders that passes search criteria */
List<FileFolder> addedFolders = new List<FileFolder>();
/* Get the folder with specified id, also include Folders
* that this folder has. No problem here works perfectly fine
* and fast */
FileFolder folder = dbSet.Include("Folders").
.Where(q => q.FileFolderID == id)
.FirstOrDefault();
if (folder!=null)
{
addedFolders.AddRange(folder.Folders.Where(f=>f.Name.Contains(searchString)));
}
return addedFolders;
}
公共列表搜索文件夹(int-id,string-searchString)
{
/*引用通过搜索条件的文件夹的占位符*/
List addedFolders=新列表();
/*获取具有指定id的文件夹,还包括文件夹
*这个文件夹有。这里没有问题,工作很好
*而且很快*/
filefolderfolder=dbSet.Include(“文件夹”)。
.Where(q=>q.FileFolderID==id)
.FirstOrDefault();
如果(文件夹!=null)
{
addedFolders.AddRange(folder.Folders.Where(f=>f.Name.Contains(searchString));
}
返回addedFolders;
}
关于您的产品线:
foreach (FileFolder f in folder.Folders)
我猜,但看起来您有一个文件夹表,其中子文件夹存储在同一个表中,ID使用FK关系链接回父ID?如果你有一个很深的文件夹层次结构,你可能会遇到一个递归问题,因为父母链接到孩子,链接到孩子,链接到孩子等等。我不知道EF(对EF不是很熟悉)会如何处理这个问题,但我猜这就是问题所在。关于你的行:
foreach (FileFolder f in folder.Folders)
/* This takes too much time as I mention, up to 9 seconds
* for 500 Folders */
我猜,但看起来您有一个文件夹表,其中子文件夹存储在同一个表中,ID使用FK关系链接回父ID?如果你有一个很深的文件夹层次结构,你可能会遇到一个递归问题,因为父母链接到孩子,链接到孩子,链接到孩子等等。我不知道EF(对EF不是很熟悉)会如何处理这个问题,但我猜这就是问题所在
/* This takes too much time as I mention, up to 9 seconds
* for 500 Folders */
记住,我是林克。事情不会马上发生。在foreach()
的第一次迭代之前,它实际上不会开始运行查询
这个查询中真正慢的是
FileFolder folder = dbSet.Include("Folders").
.Where(q => q.FileFolderID == id)
.FirstOrDefault();
真正的问题是dbSet的“文件夹”是如何定义的。你有很多内置的FK连接吗?如果是这样的话,像这样一个简单的请求就可以拉动整个数据库。这完全取决于什么依赖于“文件夹”
您甚至可以在调试器中看到这一点,当您跨过foreach循环时,您将看到它“弹出”回linq行
记住,我是林克。事情不会马上发生。在foreach()
的第一次迭代之前,它实际上不会开始运行查询
这个查询中真正慢的是
FileFolder folder = dbSet.Include("Folders").
.Where(q => q.FileFolderID == id)
.FirstOrDefault();
真正的问题是dbSet的“文件夹”是如何定义的。你有很多内置的FK连接吗?如果是这样的话,像这样一个简单的请求就可以拉动整个数据库。这完全取决于什么依赖于“文件夹”
您甚至可以在调试器中看到这一点,当您跨过foreach循环时,您将看到它“弹出”回linq行。它是ToList或FirstOrDefault。为什么两者都需要?还有为什么不使用Parallel.ForEach?我删除了ToList谢谢。从来没有使用过并行。FoeCH,我会考虑它,但它不是花费太多只为500个对象?这机器的规格是什么?英特尔I7Q740 1.7 GHz和8GB内存。为什么两者都需要?还有为什么不使用Parallel.ForEach?我删除了ToList谢谢。从来没有使用过并行。FoeCH,我会考虑它,但是它不是仅仅为500个对象花费太多吗?这个机器的规格是什么?英特尔I7Q740 1.7 GHz和8GB内存。我发现LINQ在某些情况下比迭代更快。所以我建议使用它。我发现Linq在某些情况下比迭代更快。所以我建议使用它。事实上,你粘贴的代码没有像OP那样包含.ToList()。.ToList()将强制执行查询,是吗?至少在Linq 2 SQL中是这样。@CB-当然是这样,我一定是看错了代码。啊,就像Dimitri的一样。完全正确。实际上,您粘贴的代码不包括.ToList(