我的项目中运行10-20次/页的以下查询。我试图用linq运行这个查询到sql,linq到实体,但这比它们快得多。
问题是我是否可以使用join语句将外部列表(sContentIds)传入查询,是否会使查询更快,然后使用SQL IN语句?如果是这样,我怎么能实现这一点。 sContentIds.Count大多数时间可能在1-40之间变化。
List<filterContentsPCDTO> cContents = unitOfWork.ExecuteQuery<filterContentsPCDTO>(@"SELECT c.ContentId, c.ContentPageId, c.CreatedById, p.PCA, p.PCC, p.PCD, c.AlbumId, a.AlbumTypeId
FROM Contents c
INNER JOIN Privatizations p ON c.ContentId = p.ContentId
LEFT JOIN Albums a ON c.AlbumId = a.AlbumId
WHERE c.ContentId IN (" + string.Join(",", sContentIds) + ")").ToList();
我们正在研究ASP.NET MVC4框架并使用工作单元模式进行数据库交互。通常我已经构建了这个查询,如下所示,但它比原始SQL查询慢5倍。
var cContents = unitOfWork.ContentRepository
.GetFiltered(x => contentIds.Contains(x.ContentId)).Select(x => new filterContentsPCDTO()
{
ContentId = x.ContentId,
ContentPageId = x.ContentPageId,
CreatedById = x.CreatedById,
PCA = x.Privatization.PCA,
PCC = x.Privatization.PCC,
PCD = x.Privatization.PCD,
PrivatizationModifiedById = x.Privatization.ModifiedById,
AlbumId = x.AlbumId,
albumTypeId = x.AlbumId == null ? -1 : x.Album.AlbumTypeId
}).ToList();
GetFiltered方法的实现
public IEnumerable<T> GetFiltered(
Expression<Func<T, bool>> filter = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
string includeProperties = "")
{
IQueryable<T> query = _dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query);
}
else
{
return query;
}
}
答案 0 :(得分:2)
如果您正在使用SQL Server 2008(或更新版本)并且提高性能是这里的主要目标(并且您可能愿意放弃LINQ to SQL用于此方案),我建议您编写此查询作为以user-defined table type作为参数的存储过程。这样您就可以将整个sContentIds
集合传递到数据库,并仍然可以从advantages of a stored procedures over an ad-hoc query中受益。
首先,将表类型定义为:
CREATE TYPE [dbo].[ContentList] AS TABLE(
[ContentId] [int]
)
然后按以下方式创建过程:
CREATE PROCEDURE [dbo].[usp_GetContents]
@contentIds ContentList READONLY
AS
SELECT c.ContentId
,c.ContentPageId
,c.CreatedById
,p.PCA
,p.PCC
,p.PCD
,c.AlbumId
, a.AlbumTypeId
FROM Contents c
INNER JOIN Privatizations p
ON c.ContentId = p.ContentId
LEFT JOIN Albums a
ON c.AlbumId = a.AlbumId
WHERE c.ContentId IN (SELECT ContentId FROM @contentIds)
然后你应该能够使用描述in this answer的技术从C#中调用它(基本上,从列表中创建一个DataTable
然后像常规参数一样添加它)。不幸的是looks like this is tough to do with LINQ to SQL,但正如我所说,如果提高性能是主要目标,那么这可能是一种选择。