2

我正在使用 Linq to 检索两个数据集列表。它们都在同一个数据库中,但我需要将一个表转换为我的任务表,因为它已集成到我的日历中。我敢肯定,这里不值得详细介绍,但我很想加快匹配 id 和创建新任务对象的过程。这是一个一次性完成的片段,所以即使速度很慢,我也可以简单地让程序在一夜之间运行。但是,为了将来参考,我想要一些关于提高效率的建议。

var accounts = data.Accounts.ToList().OrderBy(a => a.ID);
Incidents[] Incidents = data.Incidents.ToArray();

        for (int i=0;i<Incidents.Length;i++)
        {
            foreach (var a in accounts)
            {
                if (a.Acct_CID == Incidents[i].CustomerID)
                {
                    Tasks t = new Tasks();
                    t.creator_id = a.ID;
                    t.start_date = Incidents[i].DateOpened;
                    t.end_date = Incidents[i].DateCLosed;
                    t.product_code = Incidents[i].ProductCode;
                    t.install_type = Incidents[i].InstallType;
                    t.os = Incidents[i].OSType;
                    t.details = Incidents[i].Description;
                    t.solution = Incidents[i].Solution;
                    t.creator_name = Incidents[i].TechID;
                    t.category = Incidents[i].Title;
                    t.text = "Ticket for" + " " + Incidents[i].Name;
                    if (t.end_date == DateTime.MinValue || t.end_date == null)
                        t.status_id = 6;
                    else t.status_id = 7;
                    data.Tasks.Add(t);
                    break;
                }
            }
        }
        data.SaveChanges();
4

5 回答 5

3

为什么不即时加入表格并创建任务?

var tasks = from i in data.Incidents
            join a in data.Accounts on i.CustomerID equals a.Acct_CID
            select new Tasks()
            {
                creator_id = a.ID,
                start_date = i.DateOpened,
                end_date = i.DateCLosed
                // ...
            };

顺便说一句,我认为排序在这里没有意义,因此将创建的任务添加到数据库的顺序无关紧要。

// Query will not be executed until here
foreach(var task in tasks)
   data.Tasks.Add(task);
data.SaveChanges();
于 2012-10-15T21:09:47.343 回答
3

我会Join在 DB 上得到结果

var joinedResult = data.Accounts.Join(data.Incidents, 
                                      a => a.Acct_CID, 
                                      i => i.CustomerID, 
                                      (a, i) => new { Account = a, Incident = i });

foreach (var item in joinedResult)
{
    Tasks t = new Tasks();
    t.creator_id = item.Account.ID;
    t.start_date = item.Incident.DateOpened;
    ........

}
于 2012-10-15T21:11:02.180 回答
1

创建帐户查找

var accountsLookup = data.Accounts.ToLookup(a => a.Acct_CID);
foreach (var incident in data.Incidents)
{
    foreach (var a in accountsLookup[incident.CustomerID])
    {
        Tasks t = new Tasks();
        t.creator_id = a.ID;
        ...
    }
}
data.SaveChanges();

如果帐户是唯一的,您还可以创建字典

var accountsDict = data.Accounts.ToDictionary(a => a.Acct_CID);
foreach (var incident in data.Incidents)
{
    Account a;
    if (accountsDict.TryGetValue(incident.CustomerID, out a)
    {
        Tasks t = new Tasks();
        t.creator_id = a.ID;
        ...
    }
}
data.SaveChanges();

这将比第一个变体更快。请注意,字典具有不依赖于其大小的恒定查找时间。因此,您基本上可以获得循环的 O(n) 执行时间。您的原始实现具有 O(n^2) 执行时间。

于 2012-10-15T21:13:29.587 回答
1

替换此行

var accounts = data.Accounts.ToList().OrderBy(a => a.ID);

有了这个

var accounts = data.Accounts.OrderBy(a => a.ID).ToList();

这将让数据库进行排序,然后缓存排序的结果。你现在拥有的东西会拉入所有内容,然后在每次到达foreach循环时对它们进行排序(accounts再次枚举)。

我不能说它会带来很大的改进,但是如果你的数据集足够大,对一个大列表重新排序很多次肯定会减慢你的速度。


乍一看,您不仅accounts每次都在进行排序,而且您似乎只在寻找记录的一小部分,但您正在遍历整个数组。考虑更换

    foreach (var a in accounts)
        {
            if (a.Acct_CID == Incidents[i].CustomerID)
            {

      foreach (var a in accounts.Where(acct => acct.Acct_CID == Incidents[i].CustomerID))
      {
于 2012-10-15T20:55:19.767 回答
0
    var tasks = (from i in data.Incidents
                     join a in data.Accounts on i.CustomerID equals a.Acct_CID
                     select new
                     {
                         creator_id = a.ID,
                         start_date = i.DateOpened,
                         end_date = i.DateCLosed,
                         product_code = i.ProductCode,
                         install_type = i.InstallType,
                         os = i.OSType,
                         details = i.Description,
                         solution = i.Solution,
                         creator_name = i.TechID,
                         category = i.Title,
                         text = "Ticket for" + " " + i.Name,
                         status_id = 7
                     }).AsEnumerable().Select(x => new
                         {
                             x.creator_id,
                             x.start_date,
                             x.end_date,
                             x.product_code,
                             x.os,
                             x.details,
                             x.solution,
                             x.creator_name,
                             x.category,
                             x.text,
                             x.install_type,
                             x.status_id
                         });


        foreach (var item in tasks)
        {
            Tasks t = new Tasks();
            t.os = item.os;
            t.id = item.creator_id;
            t.install_type = item.install_type;
            t.start_date = item.start_date;
            t.end_date = item.end_date;
            t.solution = item.solution;
            t.details = item.details;
            t.creator_name = item.creator_name;
            t.category = item.category;
            t.text = item.text;
            t.product_code = item.product_code;
             if (t.end_date == DateTime.MinValue || t.end_date == null)
                 t.status_id = 6;
             else t.status_id = 7;
             data.Tasks.Add(t);
        }
        data.SaveChanges();
于 2012-10-17T16:05:37.327 回答