我使用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
员工!!!
每个角色。
我的问题是:
答案 0 :(得分:4)
使用服务器端过滤总是更好,因为您不需要将20000条记录检索到网络服务器以使用10或20个项目返回。
答案 1 :(得分: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;
}
答案 2 :(得分:1)
我会创建一个方法来加载数据库中的值,然后将它们存储在缓存中。对此方法的后续调用应返回缓存版本。然后将DataSource设置为此方法。这应该会给你一个非常好的性能提升。
http://msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx
答案 3 :(得分:1)
我认为你的解决方案应该是@PraVn和@nurgent的混合答案。编写一个存储过程,按search
字符串过滤记录。让您的DAL使用从现有网络方法调用的方法调用此SP public RadComboBoxData LoadData(RadComboBoxContext context)
答案 4 :(得分:1)
根据我的理解,为了相同的目的而一遍又一遍地向数据库发送请求对于应用程序运行状况不利。
基本上有两种方法可以使这个过程快速进行。
- 从DataBase以DataTable的形式提供数据。
- 从DataBase以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
。在没有任何DataBase跳闸的情况下将数据重新分配给控件。每当必须过滤记录时执行此步骤。
此过程将从您的数据库发送26 DataTable
。我知道它看起来很沉重。但正如您已经提到的那样,总记录将是25,000。因此,所有这些记录将在这些表之间进行划分。请参阅下面的解释。
ComboBox DataField Text column
可以有26个不同的Start With
字符。您必须根据Start with
字符划分这些记录。用A记录开头将插入第一张表。以B开头的记录将被插入到第二个表中,以C开头的记录将被插入到第三个表中,依此类推,直到用Z开始的记录将被插入到第26个表中。
请注意,您的UDT
查询最初将用于插入Local Temporary Table
中的所有记录。这个Local Temporary Table
将进一步包含26个基于Start With Character的选择语句。
以下是Sample Stored Proc。
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
,数据将从您的BLL返回为DataSet
。
仅在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 Nodes
DataSet
而不是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;
}
}
现在,您可以在ViewState
中访问此WebForm
,Combobox
可以控制DataSet
。根据我的理解,你应该选择WebService
方法。
请注意,在此上下文中不需要{{1}}。