Linq to SQL OrderBy на основе выбранного значения из DropDownList - PullRequest
0 голосов
/ 04 марта 2020

У меня есть список из 10 статей, который отображается со следующим запросом Linq - SQL в событии загрузки страницы:

if (!Page.IsPostBack)
        {
            MyDataClassesDataContext db = new MyDataClassesDataContext();

            var pressRelease = from pr in db.PressReleases
                orderby pr.DatePublished ascending 
                where pr.Published == true
                select pr;

            int i = 0;

            foreach (var release in pressRelease)
            {
                Literal literal = new Literal();
                literal.Text = "<div class='row no-gutters pb-5'><div class='col-12'><h2>" +
                               release.Title + "</h2>" + Server.HtmlDecode(release.Content) + "</h2>" +
                               "<a href='Press-Release.aspx?id=" + release.Id +
                               "'><b>Read article...</b></a></div></div>";
                pnlPressReleaases.Controls.Add(literal);
            }
        }

На моей веб-странице есть выпадающий список со следующими значениями и autopostback установлен в true.

<asp:DropDownList ID="ddlPressSortBy" AutoPostBack="True" runat="server" OnSelectedIndexChanged="ddlPressSortBy_SelectedIndexChanged">
                <asp:ListItem Value="pr.DatePublished descending">Date Published Desc</asp:ListItem>
                <asp:ListItem Selected="True" Value="pr.DatePublished ascending">Date Published Asc</asp:ListItem>
                <asp:ListItem Value="pr.Title ascending">Alphabetical</asp:ListItem>
            </asp:DropDownList>

Как только я изменяю значение выпадающего списка, возвращаемые данные не имеют порядка в соответствующем операторе выбора. Вот мой код для события OnSelectIndexChanged:

protected void ddlPressSortBy_SelectedIndexChanged(object sender, EventArgs e)
    {
        MyDataClassesDataContext db = new MyDataClassesDataContext();

        var pressRelease = from pr in db.PressReleases
            orderby ddlPressSortBy.SelectedValue
            where pr.Published == true
            select pr;


        foreach (var release in pressRelease)
        {
            Literal literal = new Literal();
            literal.Text = "<div class='row no-gutters pb-5'><div class='col-12'><h2>" +
                           release.Title + "</h2>" + Server.HtmlDecode(release.Content) + "</h2>" + "<a href='Press-Release.aspx?id=" + release.Id + "'><b>Read article...</b></a></div></div>";
            pnlPressReleaases.Controls.Add(literal);
        }
    }

Я немного не уверен, почему он не запускается с помощью orderby.

Любая помощь будет принята с благодарностью.

Спасибо, Роб

1 Ответ

1 голос
/ 04 марта 2020

Вы не можете выполнить сортировку следующим образом:

var pressRelease = from pr in db.PressReleases
        orderby ddlPressSortBy.SelectedValue
        where pr.Published == true
        select pr;

, потому что результирующий запрос будет выглядеть примерно так (предположим, что вы выбрали первый элемент):

SELECT * FROM PressReleases
WHERE Published = 1
ORDER BY 'pr.DatePublished descending'

ORDER BY предложение будет на фиксированное значение, что приводит к сортировке по умолчанию.

Linq OrderBy принимает Expression<Func<T, object>>, что было бы что-то вроде pr => pr.DatePublishing, если вы используете синтаксис Fluent. Синтаксис запроса просто скрывает это в красивой форме, но он работает так.

В соответствии с этой статьей , вы можете создать метод расширения для IQueryable, который позволит вам сортировать, используя имена свойств:

public static class extensionmethods
{
    public static IQueryable<T> OrderByField<T>(this IQueryable<T> q, string SortField, bool Ascending)
    {
        var param = Expression.Parameter(typeof(T), "p");
        var prop = Expression.Property(param, SortField);
        var exp = Expression.Lambda(prop, param);
        string method = Ascending ? "OrderBy" : "OrderByDescending";
        Type[] types = new Type[] { q.ElementType, exp.Body.Type };
        var mce = Expression.Call(typeof(Queryable), method, types, q.Expression, exp);
        return q.Provider.CreateQuery<T>(mce);
    }
}

и затем используйте его в своем коде так:

var sortingInfo = ddlPressSortBy.SelectedValue.Split(' ');
var sortingProperty = sortingInfo[0];
var descending = sortingInfo[1] == "descending";

var pressRelease = from pr in db.PressReleases
        where pr.Published == true
        select pr;
pressRelease = pressRelease.OrderByField(sortingProperty, descending);
// rest of code
...