C# LINQ为同一函数返回不同的排序顺序
在加载页面上,我设置GridView为:C# LINQ为同一函数返回不同的排序顺序,c#,entity-framework,linq,sql-order-by,C#,Entity Framework,Linq,Sql Order By,在加载页面上,我设置GridView为:myGridView.DataSource=context.Table.OrderByDescending(x=>x.Date).ToList()。然后,我将SortBy和SortDirection值保存在ViewState中:ViewState[“SortBy”]=“Date”和ViewState[“SortDirection”]=“DESC”。如果我运行SELECT*fromtable Order By Date DESC,我会得到与GridView相
myGridView.DataSource=context.Table.OrderByDescending(x=>x.Date).ToList()代码>。然后,我将SortBy和SortDirection值保存在ViewState中:ViewState[“SortBy”]=“Date”
和ViewState[“SortDirection”]=“DESC”
。如果我运行SELECT*fromtable Order By Date DESC
,我会得到与GridView相同顺序的条目(我指出这听起来很愚蠢,但请容忍)
我还有一个按钮,可以根据一些文本框过滤GridView。假设我有tbName
,tbType
,tbFrom
和tbTo
。代码是这样的:
protected void btnRefresh_Click(object sender, EventArgs e)
{
try
{
using (GasMarketerDBEntities context = new GasMarketerDBEntities())
{
if (context.Table.Count() > 0)
{
DateTime date;
List<Table> results = context.Table.ToList();
if (!string.IsNullOrEmpty(tbName.Text))
{
results = results.Where(x => x.Name == tbName.Text).ToList();
}
if (!string.IsNullOrEmpty(tbType.Text))
{
results = results.Where(x => x.Type == tbType.Text).ToList();
}
if (!string.IsNullOrEmpty(tbFrom.Text) && DateTime.TryParse(tbFrom.Text, out date))
{
results = results.Where(x => x.Date >= date).ToList();
}
if (!string.IsNullOrEmpty(tbTo.Text) && DateTime.TryParse(tbTo.Text, out date))
{
results = results.Where(x => x.Date <= date).ToList();
}
if (myGridView.EditIndex != -1)
{
//GridView is in Edit Mode
myGridView.EditIndex = -1;
}
if (ViewState["SortDirection"].ToString() == "ASC")
{
switch (ViewState["SortBy"].ToString())
{
case "Date":
results = results.OrderBy(x => x.Date).ToList();
break;
case "Name":
results = results.OrderBy(x => x.Name).ToList();
break;
case "Type":
results = results.OrderBy(x => x.Type).ToList();
break;
}
}
else
{
switch (ViewState["SortBy"].ToString())
{
case "Date":
results = results.OrderByDescending(x => x.Date).ToList();
break;
case "Name":
results = results.OrderByDescending(x => x.Name).ToList();
break;
case "Type":
results = results.OrderByDescending(x => x.Type).ToList();
break;
}
}
gvNominations.DataSource = results;
}
else
{
gvNominations.DataSource = null;
}
}
gvNominations.DataBind();
Session["DataSource"] = gvNominations.DataSource;
}
catch (Exception ex)
{
if (ex.InnerException != null)
{
while (ex.InnerException != null)
{
ex = ex.InnerException;
}
}
((System.Web.UI.HtmlControls.HtmlGenericControl)Master.FindControl("errorMessage")).InnerText = "[btnRefresh_Click]: " + ex.Message;
}
}
}
protectedvoid btnRefresh\u单击(对象发送方,事件参数e)
{
尝试
{
使用(GasMarketerDBEntities上下文=新的GasMarketerDBEntities())
{
if(context.Table.Count()>0)
{
日期时间日期;
列表结果=context.Table.ToList();
如果(!string.IsNullOrEmpty(tbName.Text))
{
results=results.Where(x=>x.Name==tbName.Text).ToList();
}
如果(!string.IsNullOrEmpty(tbType.Text))
{
results=results.Where(x=>x.Type==tbType.Text).ToList();
}
if(!string.IsNullOrEmpty(tbFrom.Text)和&DateTime.TryParse(tbFrom.Text,out-date))
{
results=results.Where(x=>x.Date>=Date.ToList();
}
如果(!string.IsNullOrEmpty(tbTo.Text)和&DateTime.TryParse(tbTo.Text,out-date))
{
results=results.Where(x=>x.Date x.Date).ToList();
打破
案例“名称”:
results=results.OrderBy(x=>x.Name.ToList();
打破
案例“类型”:
results=results.OrderBy(x=>x.Type).ToList();
打破
}
}
其他的
{
开关(ViewState[“SortBy”].ToString())
{
案件“日期”:
results=results.OrderByDescending(x=>x.Date).ToList();
打破
案例“名称”:
results=results.OrderByDescending(x=>x.Name).ToList();
打破
案例“类型”:
results=results.OrderByDescending(x=>x.Type).ToList();
打破
}
}
gvNaminations.DataSource=结果;
}
其他的
{
gvNaminations.DataSource=null;
}
}
gvNamements.DataBind();
会话[“数据源”]=gvNaminations.DataSource;
}
捕获(例外情况除外)
{
if(例如InnerException!=null)
{
while(例如InnerException!=null)
{
ex=ex.InnerException;
}
}
((System.Web.UI.HtmlControls.HtmlGenericControl)Master.FindControl(“errorMessage”)).InnerText=“[btnRefresh\u Click]:”+ex.Message;
}
}
}
如果我没有在筛选框中输入任何值并单击“刷新”,它将通过所有的“如果”检查并进入排序部分,该部分在未更改的情况下,应作为日期描述运行,并且它确实运行。奇怪的部分是results=results.OrderByDescending(x=>x.Date.ToList()代码>行运行(因此Where子句与我们在List results=context.Table.OrderByDescending(x=>x.Date).ToList()
中设置结果时相同)顺序不同。最新的条目位于顶部,但它似乎在另一个字段上排序
编辑:
删除了btnRefresh\u单击开始时设置的results
中的OrderByDescending。如果我有这样的方法,它似乎是有效的,但我想知道为什么我不能从同一个数据集开始,然后在稍后的切换块中应用OrderByDescending,并得出与在页面加载中设置OrderByDescending时相同的顺序,这是关于您的示例的一个重要点。避免在查询中过早使用.ToList()
。建立IQueryable
,然后在应用所有过滤器和排序后,使用ToList()
执行它。这是EF的一个很大的代码味道,它会导致性能的提高,并且过多的内存使用错误,人们错误地将错误归因于实体框架
例如:
List<Table> results = context.Table.ToList();
视图模型也可以安全地持久化到会话状态或您拥有的其他状态。不要持久化实体&避免将实体传递给客户端。实体应仅存在于其DbContext的范围内。将它们序列化到客户端会导致循环引用绊倒序列化程序的问题,并且如果以后尝试在另一个DbContext的范围内使用它们,也意味着关联/重新关联问题。除了根据顺序对记录进行排序之外,不保证任何排序。根据后台使用的排序方法,排序字段相同的记录不能保证顺序,也不应该期望顺序相同。@EdneyHold我同意。在PageLoad中运行时,它似乎会按日期排序,然后是a、b、c等。但是在btnRefresh\u单击方法中,如果ViewState变量没有更改,它似乎会按日期排序,然后是b、a、c等。为什么SQL生成的语句会将指定的一列日期后排序的列弄混?谢谢,我对EF很陌生,所以像这样的最佳实践非常有用!我坚持这些实体的唯一原因是因为我
using (GasMarketerDBEntities context = new GasMarketerDBEntities())
{
DateTime date;
var query = context.Table.AsQueryable;
if (!string.IsNullOrEmpty(tbName.Text))
results = results.Where(x => x.Name == tbName.Text);
if (!string.IsNullOrEmpty(tbType.Text))
results = results.Where(x => x.Type == tbType.Text);
if (!string.IsNullOrEmpty(tbFrom.Text) && DateTime.TryParse(tbFrom.Text, out date))
results = results.Where(x => x.Date >= date);
if (!string.IsNullOrEmpty(tbTo.Text) && DateTime.TryParse(tbTo.Text, out date))
results = results.Where(x => x.Date <= date);
if (myGridView.EditIndex != -1)
myGridView.EditIndex = -1;
if (ViewState["SortDirection"].ToString() == "ASC")
{
switch (ViewState["SortBy"].ToString())
{
case "Date":
results = results.OrderBy(x => x.Date);
break;
case "Name":
results = results.OrderBy(x => x.Name);
break;
case "Type":
results = results.OrderBy(x => x.Type);
break;
}
}
else
{
switch (ViewState["SortBy"].ToString())
{
case "Date":
results = results.OrderByDescending(x => x.Date);
break;
case "Name":
results = results.OrderByDescending(x => x.Name);
break;
case "Type":
results = results.OrderByDescending(x => x.Type);
break;
}
}
var results = query.ToList(); // Single ToList call to materialize.
gvNominations.DataSource = results;
gvNominations.DataBind();
// Session["DataSource"] = gvNominations.DataSource; Don't persist these entities
}
var results = query.Select(x => new TableListEntry
{
Id = x.Id,
Name = x.Name,
Date = x.Date,
Type = x.Type,
// ... etc.
}).ToList();