我正在开发一个ASP.NET,我需要在GridView中显示每个帐户的每次购买(所以基本上每个购买链接到一个帐户)。
问题是,我们有超过6000家供应商(授予,这些可以过滤到客户通常会做的大约1000个),每个供应商都会有一些交易。因此,您可以想象绑定此数据所需的时间非常长 - 实际上,SQL服务器偶尔会超时。遗憾的是,我无法使用分页,因为所有数据都需要在一个页面中显示。
我正在做的是类似于下面的代码(不在我的机器上,所以不能完全复制)
IEnumerable<Account> accs = (from s in dc.Accounts select s);
foreach (Account acc in accs)
{
IEumerable<Purchases> purchs = (from s in dc.Purchases where s.AccountID == acc.ID select s);
double 30daysval;
double 60daysval;
foreach (Purchases purch in Purchases)
{
TimeSpan span = DateTime.Now - purch.Timestamp;
if (span.Days <= 30)
{
30daysval += purch.Value;
//Add a row to the grid
}
else if (span.Days <= 60)
{
60daysval += purch.Value
//Add a row to the grid
}
}
//Add total row for that account
}
有没有更快的方法来做到这一点,也许在LINQ中使用join?我知道这可能有点无望,因为涉及的数据很大,而且在一个页面上显示几千行是相当荒谬的,但这就是我被告知要做的......
非常感谢任何想法或帮助
答案 0 :(得分:2)
// Assuming that there is no fk keys. Else you don't need joins.
var Purchases = dc.Accounts
.Join(dc.Purchases, a => a.Id, p => p.AccountId, (a,p) => new {a,p})
.Select(p);
double 30daysval;
double 60daysval;
foreach (Purchases purch in Purchases)
{
TimeSpan span = DateTime.Now - purch.Timestamp;
if (span.Days <= 30)
{
30daysval += purch.Value;
//Add a row to the grid
}
else if (span.Days <= 60)
{
60daysval += purch.Value
//Add a row to the grid
}
}
答案 1 :(得分:1)
var resuts = (from acc in dc.Accounts
join purchase in dc.Purchases on
acc.ID equals purchase.AccountID
select new {Account = acc, Purchase = purchase}).ToList();
daysVal30 = results.Where(x=>(DateTime.Now - x.Purchase.Timestamp).Days <= 30).Sum(x=>x.Purchase.Value);
daysVal60 = results.Where(x=>(DateTime.Now - x.Purchase.Timestamp).Days > 30 && (DateTime.Now - x.Purchase.Timestamp).Days <=60).Sum(x=>x.Purchase.Purchase.Value);
grid.DataSource = results;
答案 2 :(得分:1)
首先,您需要分析正在发送给数据库的SQL代码。
很有可能,对于您查询的每个帐户,都会向数据库发送一个新查询以加载您对该帐户的购买。这称为“延迟加载”或延迟加载。既然你总是需要它们,那就不是很有效了。
假设您拥有正确的外键,您可以使用LoadOptions确保只执行一个查询。
示例:
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<Account >(a => a.Purchases );
context.LoadOptions = options;
这样,所有购买都直接加载了帐户,这可能会节省大量时间。
答案 3 :(得分:0)
连接是主要的事情,但是额外的事情是有帮助的 - Linq to SQL(和Linq to Entities)不会将日期操作转换为SQL,但是它们能够将常量日期与值进行比较。
目前您正在寻找(现在 - 时间戳> 30天) - 我建议您重新安排并寻找(现在 - 30天&gt;时间戳)。您需要在C#中计算(现在 - 30天),因为表达式不会转换,但您可以在循环之前在数据库级别过滤行:
// Assuming that there is no fk keys. Else you don't need joins.
var Purchases = dc.Accounts
.Join(dc.Purchases, a => a.Id, p => p.AccountId, (a,p) => new {a,p})
.Select(p); //this is not evaluated yet
var todayAnd30 = DateTime.Now.AddDays(30); //happens instantly in memory
var todayAnd60 = DateTime.Now.AddDaye(60); //happens instantly in memory
var purchases30 = Purchases.Where(p => p.Timestamp > todayAnd30); //will translate to SQL
var purchases60 = Purchases.Where(p => p.Timestamp > todayAnd60; //will translate to SQL
foreach (Purchases purch in purchases30) //purchases30 query hits database at this point
{
30daysval += purch.Value;
//any other processing
}
foreach (Purchases purch in purchases60) //purchases60 query hits database at this point
{
60daysval += purch.Value;
//any other processing
}
归功于Holystream,我将你的答案中的连接作为保存打字的起点!
答案 4 :(得分:0)
非常感谢所有回复的人,您的建议对我帮助很大。有一件事我忘了提到这是一个挑战,他们的用户可能想看到没有购买的帐户。
我最后做的是创建我自己的类,包含一个Account对象和一个Purchase对象列表。然后我在LINQ中进行外部联接以选择每个帐户及其购买,并将结果存储到这个新类中。