如何为combobox只获取一次数据源

本文关键字:一次 数据源 获取 combobox | 更新日期: 2023-09-27 18:30:14

我使用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;
            }}

我的问题是:

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

每个角色。

我的问题是:

  • 这么糟糕的行为怎么会这么快
  • 有没有办法让所有员工只参加一次
  • 如何提高性能

如何为combobox只获取一次数据源

使用服务器端过滤总是更好的,因为您不需要将20000条记录检索到Web服务器,就可以使用10或20个项目来返回。

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

根据我的理解,出于同样的目的反复向数据库发送请求对应用程序的健康状况不利。

基本上有两种方法可以使流程快速进行。

  1. 从数据库中取出DataTable形式的数据
  2. 从数据库中获取数据集形式的数据

DataTable方法

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

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。我知道它看起来很重。但正如你已经提到的,总记录将是25000。因此,所有这些记录都将在这些表格中进行划分。请参阅下面的解释。

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

请注意,您的UDT查询最初将用于插入Local Temporary Table中的所有记录。该Local Temporary Table将进一步具有26个基于"以字符开头"的select语句。

以下是示例存储过程。

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的意义在于,在表的for中,记录被进一步划分为子节点。您的Search expression将在DataSetSplitted Nodes上实现,而不是在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本身中添加以下属性。如果ViewState为空,下面的Property将从数据库返回结果集。否则,它将仅返回ViewState保留的数据。

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

现在,您可以在您的WebForm中访问此ViewState,在那里您可以控制Combobox。根据我的理解,你应该选择DataSet方法。

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

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

下面是我的一个asmx服务的例子,它填充了一个radcombox:

    [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;
    }

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

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

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