1

我用telerik:RadComboBox

像这样 :

<telerik:RadComboBox runat="server" ID="RadComboBox1"  EnableLoadOnDemand="true"
                                            ShowMoreResultsBox="true" EnableVirtualScrolling="true" CollapseDelay="0" Culture="ar-EG" ExpandDelay="0" Filter="StartsWith" ItemsPerRequest="100"
                                            MarkFirstMatch="true" Skin="Outlook" ValidationGroup="L" Width="202px" EnableAutomaticLoadOnDemand="True"
                                            EmptyMessage="-Enter user name-"
                                            EnableItemCaching="true" >
                                            <WebServiceSettings Path="../WebService/Employees.asmx" Method="LoadData" />


和我的网络服务:

 [System.Web.Script.Services.ScriptService]
    public class Employees : System.Web.Services.WebService
    {

        [WebMethod(EnableSession = true)]  
            public RadComboBoxData LoadData(RadComboBoxContext context)
                {

                RadComboBoxData result = new RadComboBoxData();
                DataTable dt = FollowsDAL.GetAllEmployees();

                var allEmployees = from r in dt.AsEnumerable()

                                   orderby r.Field<string>("name")

                                   select new RadComboBoxItemData
                                   {
                                       Text = r.Field<string>("name").ToString().TrimEnd()
                                   };
                string text = context.Text;
                if (!String.IsNullOrEmpty(text))
                {
                    allEmployees = allEmployees.Where(item => item.Text.StartsWith(text));
                }
                //Perform the paging
                // - first skip the amount of items already populated
                // - take the next 10 items
                int numberOfItems = context.NumberOfItems;
                var employees = allEmployees.Skip(numberOfItems).Take(100);


                result.Items = employees.ToArray();


                int endOffset = numberOfItems + employees.Count();
                int totalCount = allEmployees.Count();

                //Check if all items are populated (this is the last page)
                if (endOffset == totalCount)
                    result.EndOfItems = true;

                //Initialize the status message
                result.Message = String.Format("Items <b>1</b>-<b>{0}</b> out of <b>{1}</b>",
                                               endOffset, totalCount);

                return result;
            }}

我的问题是:

虽然这个控件非常快,但每次我首先输入特定名称时,它都会在数据20000表中获取员工dt

与每个字符。

我的问题是:

  • 这种不良行为怎么会这么快?
  • 有没有办法让所有员工只得到一次?
  • 如何提升业绩?
4

5 回答 5

4

使用服务器端过滤总是更好,因为您不需要将 20000 条记录检索到网络服务器以使用 10 或 20 项返回。

http://demos.telerik.com/aspnet-ajax/combobox/examples/populatingwithdata/autocompletesql/defaultcs.aspx

于 2012-04-07T08:43:41.583 回答
2

您的 DAL 应该有一种方法来根据发送的文本过滤结果,然后将它们添加到组合框中。我的 DAL 是 Telerik OpenAccess ORM (Linq2SQL),但您也可以编写一个存储过程来过滤结果。

这是我的一个填充 radcombobox 的 asmx 服务的示例:

    [WebMethod]
    public RadComboBoxData FindEmployee(RadComboBoxContext context)
    {
        RadComboBoxData comboData = new RadComboBoxData();

        using (DataBaseContext dbc = new DataBaseContext())
        {
            IQueryable<Employee> Employees = dbc.FindEmployee(context.Text);

            int itemOffset = context.NumberOfItems;
            int endOffset = Math.Min(itemOffset + 10, Employees.Count());
            List<RadComboBoxItemData> result = new List<RadComboBoxItemData>();

            var AddingEmployees = Employees.Skip(itemOffset).Take(endOffset - itemOffset);
            foreach (var Employee in AddingEmployees)
            {
                RadComboBoxItemData itemData = new RadComboBoxItemData();
                itemData.Text = Employee.Person.FullName;
                itemData.Value = Employee.EmployeeID.ToString();

                result.Add(itemData);
            }


            comboData.EndOfItems = endOffset == Employees.Count();
            comboData.Items = result.ToArray();
            if (Employees.Count() <= 0)
                comboData.Message = "No matches";
            else
                comboData.Message = String.Format("Items <b>1</b>-<b>{0}</b> out of <b>{1}</b>", endOffset, Employees.Count());
            return comboData;
        }
    }

如果您想知道我的 FindEmployee 方法是什么:

public IQueryable<Employee> FindEmployee(string SearchString, bool IncludeInactive = false)
    {
        return from e in this.Employees
               where
                    (e.EmployeeID.ToString() == SearchString ||
                     e.Person.FirstName.Contains(SearchString) ||
                     e.Person.MiddleName.Contains(SearchString) ||
                     e.Person.LastName.Contains(SearchString) ||
                     (e.Person.FirstName + " " + e.Person.LastName).Contains(SearchString) ||
                     (e.Person.FirstName + " " + e.Person.MiddleName).Contains(SearchString) ||
                     (e.Person.FirstName + " " + e.Person.MiddleName + " " + e.Person.LastName).Contains(SearchString)) &&
                    ((e.Inactive == false || e.Inactive == null) && IncludeInactive == false)
               select e;
    }
于 2012-04-10T13:28:46.213 回答
1

我将创建一个从数据库加载值然后将它们存储在缓存中的方法。对该方法的后续调用应返回缓存版本。然后将 DataSource 设置为此方法。这应该会给您带来非常好的性能提升。

http://msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx

于 2012-04-08T05:15:33.283 回答
1

我认为您的解决方案应该是@PraVn 和@nurgent 的混合答案。search编写一个按字符串过滤记录的存储过程。让您的 DAL 使用从您现有的 Web 方法调用的方法调用此 SPpublic RadComboBoxData LoadData(RadComboBoxContext context)

于 2012-04-11T13:26:07.203 回答
1

据我了解,为了相同的目的一遍又一遍地向数据库发送请求不利于应用程序的健康。

基本上有两种方法可以加快这个过程。

  1. 从您的数据库中以 DataTable 的形式获取数据。
  2. 从您的数据库中以 DataSet 的形式获取数据。

数据表方法

Database在表单加载期间从 中获取所有记录。将其保存在 中ViewState而不是Session. 请注意这一点。像下面这样访问数据.. 现在访问ViewState. Type Cast它并访问下面提到的功能。

public static class GetFilteredData
{
    public static DataTable FilterDataTable(this DataTable Dt, string FilterExpression)
    {
        using (DataView Dv = new DataView(Dt))
        {
            Dv.RowFilter = FilterExpression;
            return Dv.ToTable();
        }
    }
}


DataTableObject.FilterDataTable("Search Expression or your string variable")

这将返回您的DataTable. 将数据重新分配给控件,而不发生任何数据库故障。每当您必须过滤记录时执行此步骤。

数据集方法

此过程26 DataTable将从您的数据库发送。我知道它看起来很重。但正如您已经提到的,总记录将是 25,000 条。因此,所有这些记录都将在这些表中进行划分。请看下面的解释。

ComboBox DataField Text column可以有 26 个不同的Start With字符。您必须根据Start with字符来划分这些记录。以 A 开头的记录将被插入到 First Table。以 B 开头的记录将被插入到第二个表中,以 C 开头的记录将被插入到第三个表中,依此类推,直到以 Z 开头的记录将被插入到第 26 个表中。

请注意,您的UDT查询最初将用于将所有记录插入到Local Temporary Table. 这Local Temporary Table将进一步有 26 个基于以字符开头的选择语句。

下面是示例存储过程。

Create Proc ProcName
As

Create Table #Temp
(
    ColumnName Varchar(50)
)

Insert into #Temp(ColumnName)
Select ColumnName from YourTableName

Select ColumnName From #Temp Where ColumnName like 'a%'
Select ColumnName From #Temp Where ColumnName like 'b%'
Select ColumnName From #Temp Where ColumnName like 'c%'
--UpTo Z

现在,你终于有了26 Tables,数据DataSet将从你的 BLL 返回。只保留它ViewState。现在将过滤数据,请使用下面提到的功能。

public static class GetFilteredData
{
    public static DataTable FilterDataTable(this DataSet Dt, string FilterExpression)
    {
        string Lowercase = FilterExpression.ToLower();
        Int16 TableID = 0;
        if (Lowercase.StartsWith("a"))
        {
            TableID = 0;
        }
        else if (Lowercase.StartsWith("b"))
        {
            TableID = 1;
        }
        else if (Lowercase.StartsWith("c"))
        {
            TableID = 2;
        }
        //upTo Z
        using (DataView Dv = new DataView(Dt.Tables[TableID]))
        {
            Dv.RowFilter = FilterExpression;
            return Dv.ToTable();
        }
    }
}

所以我们理解使用的意义DataSet Technique在于,将记录进一步划分为表中的子节点。您Search expression将在Splitted NodesDataSet不是Original DataSet.


根据原始查询中提到的代码修改

仅在您的 Web 应用程序/网站中添加以下内容。

public static class GetFilteredData
{
    public static DataTable FilterDataTable(this DataTable Dt, string FilterExpression)
    {
        using (DataView Dv = new DataView(Dt))
        {
            Dv.RowFilter = FilterExpression;
            return Dv.ToTable();
        }
    }
}

WebForm在自身中添加以下属性。以下Property将在ViewState为空的情况下从数据库返回结果集。否则它将ViewState只返回保留的数据。

public DataTable Employees
{
    get
    {
        if (ViewState["Employees"] == null)
        {
            return FollowsDAL.GetAllEmployees();
        }
        return (DataTable)ViewState["Employees"];
    }
    set
    {
        ViewState["Employees"] = value;
    }
}

现在您可以ViewStateWebForm您可以Combobox控制的地方访问它。根据我的理解,您应该选择DataSetApproach。

请注意,WebService在此上下文中不需要。

于 2012-04-12T02:24:23.857 回答