Мне нужно переместить фильтрацию сложного объекта из Linq в SQL в хранимую процедуру, потому что мне нужно загрузить данные в память, чтобы применить некоторые фильтры с помощью ToList (). Запрос Linq вызывает тайм-аут некоторых поисков. Когда я переключился на хранимую процедуру, я изменил функцию следующим образом:
private IQueryable<ProposalLogVM> ApplyProposalSearch(IndexSearchVM search)
{
SqlParameter YearCode;
SqlParameter ProposalStatus;
SqlParameter Company;
SqlParameter SearchString;
if (!String.IsNullOrWhiteSpace(search.SearchString) && search.Year == null)
{
search.Year = DateTime.Now.Year;
}
if (!String.IsNullOrWhiteSpace(search.Year.ToString()))
{
YearCode = new SqlParameter("@Year", search.Year.ToString());
}
else
{
YearCode = new SqlParameter("@Year", DBNull.Value);
}
if (!String.IsNullOrWhiteSpace(search.ProposalStatus))
{
ProposalStatus = new SqlParameter("@ProposalStatus", search.ProposalStatus);
}
else
{
ProposalStatus = new SqlParameter("@ProposalStatus", DBNull.Value);
}
if (!String.IsNullOrWhiteSpace(search.CompanyID.ToString()))
{
Company = new SqlParameter("@CompanyID", search.CompanyID.ToString());
}
else
{
Company = new SqlParameter("@CompanyID", DBNull.Value);
}
if (!String.IsNullOrWhiteSpace(search.SearchString))
{
SearchString = new SqlParameter("@SearchString", search.SearchString);
}
else
{
SearchString = new SqlParameter("@SearchString", DBNull.Value);
}
var proposals = _dbpm.Database.SqlQuery<ProposalLogVM>("EXEC spSearchProposals @Year, @ProposalStatus, @CompanyID, @SearchString", YearCode, ProposalStatus, Company, SearchString).AsQueryable();
switch (search.SortOption)
{
case "ProposalNumber":
proposals = proposals.OrderBy(p => p.ProposalNumber);
break;
case "ProjectName":
proposals = proposals.OrderBy(p => p.ProjectName);
break;
case "ProjectNameD":
proposals = proposals.OrderByDescending(p => p.ProjectName);
break;
case "BidDate":
proposals = proposals.OrderBy(p => p.BidDate);
break;
case "BidDateD":
proposals = proposals.OrderByDescending(p => p.BidDate);
break;
case "Owner":
proposals = proposals.OrderBy(p => p.Owner);
break;
case "OwnerD":
proposals = proposals.OrderByDescending(p => p.Owner);
break;
default:
proposals = proposals.OrderByDescending(p => p.ProposalNumber);
break;
}
return proposals;
}
Теперь я получаю «SqlParameter уже содержится в другой SqlParameterCollection». при выполнении строки
// get the raw proposal list, but don't execute or copy to memory
IQueryable<ProposalLogVM> rawProposals = ApplyProposalSearch(viewModel.Search);
// Allow ToPagedList() to do the hard work
viewModel.Proposals = rawProposals.ToPagedList((int)viewModel.Search.Page, (int)viewModel.Search.Lines);
Если я просто выполню строку:
var proposals = _dbpm.Database.SqlQuery<ProposalLogVM>("spSearchProposals @Year, @ProposalStatus, @CompanyID, @SearchString", YearCode, ProposalStatus, Company, SearchString).AsQueryable().ToList();
Он работает нормально и возвращает все 390 000 ожидаемых записей.
Я провел последние несколько часов, читая все остальные статьи о переполнении стека и пробуя эти решения, но ни одна из них, похоже, не работает.