Ответ 1
Проводя это как ответ, а не редактирование на мой вопрос:
Взяв некоторую информацию, предоставленную @Drauka (и google), вот что я сделал для своей начальной итерации.
- Создал хранимую процедуру для полнотекстового поиска. Это было слишком сложно сделать в EF, даже если поддерживается (в качестве одного из примеров некоторые из моих сущностей связаны с бизнес-логикой, и я хотел бы сгруппировать их, возвращаясь как единственный результат). Хранимая процедура сопоставляется с DTO с идентификатором объекта и рангом.
- Я изменил этот фрагмент блога/код, чтобы сделать вызов хранимой процедуры, и заполнить мой DTO: http://www.lucbos.net/2012/03/calling-stored-procedure-with-entity.html
-
Я заполняю свой объект результатов итогами и информацией поискового вызова из результатов хранимой процедуры, а затем просто загружаю объекты для текущей страницы результатов:
int[] projectIDs = new int[Settings.Default.ResultsPerPage]; foreach (ProjectFTS_DTO dto in RankedSearchResults .Skip(Settings.Default.ResultsPerPage * (pageNum - 1)) .Take(Settings.Default.ResultsPerPage)) { projectIDs[index] = dto.ProjectID; index++; } IEnumerable<Project> projects = _repository.Projects .Where(o=>projectIDs.Contains(o.ProjectID));
Полная реализация:
Поскольку этот вопрос получает много просмотров, я подумал, что, возможно, стоит опубликовать более подробные сведения о моем окончательном решении для других, помогая или возможное улучшение.
Полное решение выглядит так:
Класс DatabaseExtensions:
public static class DatabaseExtensions {
public static IEnumerable<TResult> ExecuteStoredProcedure<TResult>(
this Database database,
IStoredProcedure<TResult> procedure,
string spName) {
var parameters = CreateSqlParametersFromProperties(procedure);
var format = CreateSPCommand<TResult>(parameters, spName);
return database.SqlQuery<TResult>(format, parameters.Cast<object>().ToArray());
}
private static List<SqlParameter> CreateSqlParametersFromProperties<TResult>
(IStoredProcedure<TResult> procedure) {
var procedureType = procedure.GetType();
var propertiesOfProcedure = procedureType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
var parameters =
propertiesOfProcedure.Select(propertyInfo => new SqlParameter(
string.Format("@{0}",
(object) propertyInfo.Name),
propertyInfo.GetValue(procedure, new object[] {})))
.ToList();
return parameters;
}
private static string CreateSPCommand<TResult>(List<SqlParameter> parameters, string spName)
{
var name = typeof(TResult).Name;
string queryString = string.Format("{0}", spName);
parameters.ForEach(x => queryString = string.Format("{0} {1},", queryString, x.ParameterName));
return queryString.TrimEnd(',');
}
public interface IStoredProcedure<TResult> {
}
}
Класс для хранения сохраненных входов proc:
class AdvancedFTS :
DatabaseExtensions.IStoredProcedure<AdvancedFTSDTO> {
public string SearchText { get; set; }
public int MinRank { get; set; }
public bool IncludeTitle { get; set; }
public bool IncludeDescription { get; set; }
public int StartYear { get; set; }
public int EndYear { get; set; }
public string FilterTags { get; set; }
}
Объект результатов:
public class ResultsFTSDTO {
public int ID { get; set; }
public decimal weightRank { get; set; }
}
Наконец, вызов хранимой процедуры:
public List<ResultsFTSDTO> getAdvancedFTSResults(
string searchText, int minRank,
bool IncludeTitle,
bool IncludeDescription,
int StartYear,
int EndYear,
string FilterTags) {
AdvancedFTS sp = new AdvancedFTS() {
SearchText = searchText,
MinRank = minRank,
IncludeTitle=IncludeTitle,
IncludeDescription=IncludeDescription,
StartYear=StartYear,
EndYear = EndYear,
FilterTags=FilterTags
};
IEnumerable<ResultsFTSDTO> resultSet = _context.Database.ExecuteStoredProcedure(sp, "ResultsAdvancedFTS");
return resultSet.ToList();
}