我正在使用LINQ来访问我的数据库表。有些表可能有(数十万)记录。
使用如下语句从表中读取:
var records = db.Logs;
会使应用程序非常慢。它会一次加载所有记录。
我需要使用多个条件过滤结果,例如:
if (UserID != null)
{
records = records.Where(r => r.User == UserID);
}
if (UserIP != null)
{
records = records.Where(r => r.IP == UserIP);
}
问题是我第一次从表中读取会给我带来所有记录,并会使应用程序变慢。
有没有办法在LINQ语句中创建条件(if,switch),就像我们以前的SQL语句一样?
这是多久以来创建的逻辑:
string sql = "SELECT * FROM Log WHERE 1=1";
if (UserID != null)
{
sql += " AND User = '" + UserID + "'";
}
if (UserIP != null)
{
sql += " AND IP = '" + UserIP + "'";
}
sqlCmd.query(sql);
答案 0 :(得分:6)
实际上是这样的作业:
var records = db.Logs;
不立即执行查询。它只准备稍后使用的数据结构。查询的执行仅在代码需要数据时发生,并且任何where子句都集成在查询中,从而阻止它返回整个表。
完全可以做这样的事情:
var records = db.Logs;
if (filter1) records = records.Where(r => r.Field1 == condition1);
if (filter2) records = records.Where(r => r.Field2 == condition2);
这将以执行一个查询结束,其中包含(种类)动态where语句。
但是你应该定义正确的索引。
答案 1 :(得分:2)
我认为你错了。对db.Logs的调用应返回IQueryable - 这意味着在需要检索数据之前不会执行查询。例如,您访问Log类的属性或将您的集合转换为列表.ToList()
答案 2 :(得分:2)
什么是db.Logs
?不是IEnumerable<T>
或IQueryable<T>
吗?通常在Linq2SQL中,在您调用.ToArray
或.ToList
之前不会执行查询,因此您可以先构建查询树。
答案 3 :(得分:1)
问题是我第一次从表中读取会给我带来所有记录,并会使应用程序变慢。
var records = db.Logs
不从表中读取。除了创建查询之外,您还没有做任何事情(它类似于创建SQL命令文本而不将命令文本发送到数据库执行)。打开允许您查看发送到数据库的SQL命令的功能,您将看到此行代码不会向数据库发送任何内容。事实上,这一行也没有:
records = records.Where(r => r.User == UserID);
这只是修改名为records
的查询(您应该称之为recordsQuery
)以在User
上添加条件。直到您遍历查询,它才会实际发送到数据库执行。所以要么
records.ToList();
或
foreach(var record in records) {
// something something
}
或许多其他执行查询的方式。
这是多久以来创建的逻辑:
我希望不是。你好注射攻击!
某些表可能有(数十万)记录。
成千上万的人没有。
答案 4 :(得分:1)
最好使用Paging,让你的数据做你想做的任何事情,然后再获得另一页。
答案 5 :(得分:0)
试试这个:
List<Records> records;
if (UserID != null)
{
records = db.Logs.Where(r => r.User == UserID).ToList();
}
else
{
records = db.Logs.ToList();
}
答案 6 :(得分:0)
假设您正在使用SQL Server,那么数十万行远非庞大。
回到主题,如果你传递IQueryable<T>
,那么每次枚举时都会执行SQL。如果您的旧代码是正确的并且您的新代码很慢,这很可能是您的问题。您可以通过调用ToList()
,将其转换为IEnumerable<T>
并将所有数据放入内存来避免这种情况。
最后,您可以通过调用.Skip(PageSize * PageIndex).Take(PageSize)
来分页数据。
答案 7 :(得分:-1)
如果使用lambda表达式,则在使用它之前不会执行查询,例如转换为列表或枚举所有数据。
var filtered = (from l in db.Logs
where l => l.User == UserID
select l).ToList();