0

I have a list of 10 articles which gets displayed with the following Linq to SQL query in the page load event:

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

On my web page, I have a dropdownlist with the following values and the autopostback set to 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>

Once I change the value of the dropdownlist, the data returned has no orderby on the corresponding select statement. Here is my code for the OnSelectIndexChanged event:

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

I'm a little unsure why it is not firing with the orderby.

Any help would be greatly appreciated.

Thanks Rob

Robert
  • 75
  • 1
  • 7
  • I think you'll find your answer here: https://stackoverflow.com/questions/31955025/generate-ef-orderby-expression-by-string – Mike-314 Mar 04 '20 at 17:03
  • what are the values in `ddlPressSortBy` are there a lot or only 1 or 2 -- it is easier if it is just a few values – Hogan Mar 04 '20 at 18:25

1 Answers1

1

You cannot do sorting this way:

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

because resulting query would be something like (suppose you selected the first item):

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

ORDER BY clause would be by a fixed value, resulting in default sorting.

Linq OrderBy takes an Expression<Func<T, object>>, that would be something like pr => pr.DatePublishing, if you are using Fluent syntax. Query syntax just hides that in pretty form, but it how it works.

Accordingly to this article, you could create an extension method for IQueryable that allows you to sort using property names:

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

and then use it in your code like this:

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
Claudio Valerio
  • 2,302
  • 14
  • 24