如何为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
员工!!!
每个角色。
我的问题是:
- 这么糟糕的行为怎么会这么快
- 有没有办法让所有员工只参加一次
- 如何提高性能
使用服务器端过滤总是更好的,因为您不需要将20000条记录检索到Web服务器,就可以使用10或20个项目来返回。
http://demos.telerik.com/aspnet-ajax/combobox/examples/populatingwithdata/autocompletesql/defaultcs.aspx
根据我的理解,出于同样的目的反复向数据库发送请求对应用程序的健康状况不利。
基本上有两种方法可以使流程快速进行。
- 从数据库中取出DataTable形式的数据
- 从数据库中获取数据集形式的数据
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
将在DataSet
的Splitted 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)
调用