2010-09-29 2 views
0

У меня есть страница поиска, на которой задано поиск 3,5 миллионов записей для физических лиц на основе их имени, идентификатора клиента, адреса и т. Д. Запросы варьируются от сложных до простых.Использование объекта ObjectDataSource с GridView в динамическом сценарии

В настоящее время этот код основан на SqlDataSource и GridView. Когда пользователь вводит термин serach и нажимает клавишу ввода, TextBoxChanged даже запускает функцию Search (term, type), которая изменяет запрос, используемый SqlDataSource, добавляет параметры и перенастраивает GridView.

Это хорошо работает, но я стал одержим переписыванием кода более эффективно. Я хочу, чтобы пейджинг выполнялся SQL Server вместо неэффективности SqlDataSource в режиме DataSet.

Введите объект ObjectDataSource. Предостережение: Я никогда не использовал его до сегодняшнего дня.

Я провел большую часть дня вместе положить этот класс:

using System; 
using System.Data; 
using System.Data.SqlClient; 
using System.Configuration; 
using System.Text; 
using System.Web; 
using System.Web.Security; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Web.UI.WebControls.WebParts; 
using System.Web.UI.HtmlControls; 

/// <summary> 
/// Summary description for MultiSearchData 
/// </summary> 
public class MultiSearchData 
{ 
    private string _connectionString = string.Empty; 
    private string _sortColumns = string.Empty; 
    private string _selectQuery = string.Empty; 
    private int _lastUpdate; 
    private int _lastRowCountUpdate; 
    private int _lastRowCount; 
    private SqlParameterCollection _sqlParams; 

    public MultiSearchData() 
    { 

    } 

    private void UpdateDate() 
    { 
     _lastUpdate = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; 
    } 

    private string ReplaceFirst(string text, string search, string replace) 
    { 
     int pos = text.IndexOf(search); 
     if (pos < 0) 
     { 
      return text; 
     } 
     return text.Substring(0, pos) + replace + text.Substring(pos + search.Length); 
    } 

    public string SortColumns 
    { 
     get { return _sortColumns; } 
     set { _sortColumns = value; } 
    } 

    public SqlParameterCollection SqlParams 
    { 
     get { return _sqlParams; } 
     set { _sqlParams = value; } 
    } 

    public string ConnectionString 
    { 
     get { return _connectionString; } 
     set { _connectionString = value; } 
    } 

    public string SelectQuery 
    { 
     get { return _selectQuery; } 
     set 
     { 
      if (value != _selectQuery) 
      { 
       _selectQuery = value; 
       UpdateDate(); 
      } 
     } 
    } 

    public DataTable GetFullDataTable() 
    { 
     return GetDataTable(AssembleSelectSql()); 
    } 

    public DataTable GetPagedDataTable(int startRow, int pageSize, string sortColumns) 
    { 
     if (sortColumns.Length > 0) 
      _sortColumns = sortColumns; 

     return GetDataTable(AssemblePagedSelectSql(startRow, pageSize)); 
    } 

    public int GetRowCount() 
    { 

     if (_lastRowCountUpdate == _lastUpdate) 
     { 
      return _lastRowCount; 
     } 
     else 
     { 
      string strCountQuery = _selectQuery.Remove(7, _selectQuery.IndexOf("FROM") - 7); 
      strCountQuery = strCountQuery.Replace("SELECT FROM", "SELECT COUNT(*) FROM"); 

      using (SqlConnection conn = new SqlConnection(_connectionString)) 
      { 
       conn.Open(); 
       using (SqlCommand cmd = new SqlCommand(strCountQuery, conn)) 
       { 
        if (_sqlParams.Count > 0) 
        { 
         foreach (SqlParameter param in _sqlParams) 
         { 
          cmd.Parameters.Add(param); 
         } 
        } 
        _lastRowCountUpdate = _lastUpdate; 
        _lastRowCount = (int)cmd.ExecuteScalar(); 
        return _lastRowCount; 
       } 
      } 
     } 
    } 

    public DataTable GetDataTable(string sql) 
    { 
     DataTable dt = new DataTable(); 

     using (SqlConnection conn = new SqlConnection(_connectionString)) 
     { 
      using (SqlCommand GetCommand = new SqlCommand(sql, conn)) 
      { 
       conn.Open(); 

       if (_sqlParams.Count > 0) 
       { 
        foreach (SqlParameter param in _sqlParams) 
        { 
         GetCommand.Parameters.Add(param); 
        } 
       } 
       using (SqlDataReader dr = GetCommand.ExecuteReader()) 
       { 
        dt.Load(dr); 
        conn.Close(); 
        return dt; 
       } 
      } 
     } 


    } 

    private string AssembleSelectSql() 
    { 
     StringBuilder sql = new StringBuilder(); 

     sql.Append(_selectQuery); 

     return sql.ToString(); 
    } 

    private string AssemblePagedSelectSql(int startRow, int pageSize) 
    { 
     StringBuilder sql = new StringBuilder(); 
     string originalQuery = ReplaceFirst(_selectQuery, "FROM", ", ROW_NUMBER() OVER (ORDER BY " + _sortColumns + ") AS ResultSetRowNumber FROM"); 
     sql.Append("SELECT * FROM ("); 
     sql.Append(originalQuery); 
     sql.Append(") AS PagedResults"); 
     sql.AppendFormat(" WHERE ResultSetRowNumber > {0} AND ResultSetRowNumber <= {1}", startRow.ToString(), (startRow + pageSize).ToString()); 

     return sql.ToString(); 
    } 
} 

Я не знаю, если это красиво. Оно работает. Я даю запрос в методе ObjectCreating:

protected void dataMultiSearchData_ObjectCreating(object sender, ObjectDataSourceEventArgs e) 
{ 
    MultiSearchData info; 
    info = Cache["MultiSearchDataObject"] as MultiSearchData; 

    if (null == info) 
    { 
     info = new MultiSearchData(); 
    } 


    info.SortColumns = "filteredcontact.fullname"; 
    info.ConnectionString = "Data Source=SERVER;Initial Catalog=TheDatabase;Integrated Security=sspi;Connection Timeout=60"; 
    info.SelectQuery = @"SELECT filteredcontact.contactid, 
           filteredcontact.new_libertyid, 
           filteredcontact.fullname, 
           '' AS line1, 
           filteredcontact.emailaddress1, 
           filteredcontact.telephone1, 
           filteredcontact.birthdateutc AS birthdate, 
           filteredcontact.gendercodename 
         FROM filteredcontact 
         WHERE fullname LIKE 'Griffin%' AND filteredcontact.statecode = 0"; 

    e.ObjectInstance = info; 
} 
protected void dataMultiSearchData_ObjectDisposing(object sender, ObjectDataSourceDisposingEventArgs e) 
{ 
    MultiSearchData info = e.ObjectInstance as MultiSearchData; 

    MultiSearchData temp = Cache["MultiSearchDataObject"] as MultiSearchData; 

    if (null == temp) 
    { 
     Cache.Insert("MultiSearchDataObject", info); 
    } 

    e.Cancel = true; 
} 

После того, как класс имеет запрос, он заворачивает его в пейджинг дружественную SQL и мы прочь к гонкам. Я реализовал кэширование, чтобы он мог пропустить некоторые дорогие запросы. И т. Д.

Моя проблема в том, что это полностью разрушает мой довольно маленький мир поиска (термин, тип). Если задать запрос в методе ObjectCreating, он полностью сует меня.

Я пытаюсь думать о лучшем способе делать это весь день, но я все время заканчиваю действительно грязным ... делаю все это в модели ObjectCreating, которая просто превращает мой живот.

Как вы это сделаете? Как я могу сохранить эффективность этого нового метода, имея организационную простоту моей прежней модели?

Неужели я слишком OCD?

+0

Метод ObjectCreating над термином запроса inline. Связанный класс поддерживает параметры, я его еще не реализовал, так как у меня возникли проблемы с тем, как организовать реализацию. :) – clifgriffin

+0

Почему вы не используете хранимые процедуры? использование inline sql - это боль для поддержания. –

+0

Или еще лучше, ОРМ. Очень легко взять запрос LINQ и преобразовать его в запрос графа или сделать его страницей с безопасностью типа и т. Д. – StriplingWarrior

ответ

0

Я решил, что это невозможно. Более того, после сравнения этого класса я обнаружил, что он работает не лучше, чем SqlDataSource, но его гораздо сложнее поддерживать.

Таким образом, я отказался от этого проекта. Надеюсь, кто-то найдет этот код полезным в какой-то момент.

Смежные вопросы