我是实体框架的新手,想知道这个函数是否可以优化。本质上,我想做的是得到一个在过去3天内发生的所有唯一ID的列表。然后提取每个ID的最后6条记录。下面的方法对我很有效,但我想知道这个方法是否可以针对1000条记录进行优化。
我的结构如下所示
public class ModelMessage
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ModelMessageId { get; set; }
public string TaskId { get; set; }
public string Msg { get; set; }
public DateTime DateAdded { get; set; }
}
这就是我正在做的
private List<ModelMessage> Results()
{
//last 3 days
int days = days * -1;
List<ModelMessage> collection = new List<ModelMessage>();
DateTime currenteDate = DateTime.UtcNow.Date.AddDays(days);
DbContext dbcontext = new DbContext(ConString);
//Get all the unique ids that were added 3 days ago
List<string> listIds = dbcontext.Messages.Where(x => (x.DateAdded > currenteDate)).Select(x => x.TaskId).Distinct().ToList();
foreach (string id in listIds)
{
//Get the last 6 records of each of those ids
collection.AddRange(dbcontext.Messages.Where(x => (x.TaskId == id)).OrderBy(order => order.DateAdded).TakeLast(6));
}
return collection;
}
}
任何建议或想法,如果这个方法可以优化(C#和实体相关)的速度和性能。
3条答案
按热度按时间bogh5gae1#
在EF中编写查询逻辑时,尽量不要运行多个查询。每次运行
foreach
、ToList()
、First()
等时,都是在 * 运行 * 查询。相反,将查询(IQueryable)组合在一起,并在最后运行查询,如下所示:
对于SQL Server,它将转换为单个SQL查询。在EF Core中:
EF6生成的查询略有不同,但逻辑上是等效的:
fgw7neuy2#
您的代码效率非常低,因为它要拉回整个列表,然后再将其推回到服务器,而且它实际上是一个自连接。
我认为最好使用窗口函数来完成。不确定是否有任何方法可以在实体框架中不执行原始SQL来完成此操作,但您需要的SQL将类似于以下内容:
如果有人能把这个翻译成EF,请随意添加到我的答案中。
vhipe2zx3#
您可以使用
IQueryable<T>
的GroupBy
扩展方法:GroupBy
返回一个IGrouping<TKey,TElement>,您可以对其进行迭代以获取每组TElement
。