使用 ODS、BusinessLayer 和 Dynamic Linq 的 ListView 无法排序

发布于 2024-11-05 16:40:44 字数 5735 浏览 0 评论 0原文

症状:ListView 不排序

数据层: Linq 生成的类,包括 Northwind Employee 表和 System.Linq.Dynamic 类

业务层:

namespace BusinessLayer
{
    [Serializable]
    public class EmployeeData
    {
        public int EmployeeId { get; set; }
        public int? ReportsToId { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string Title { get; set; }
        public DateTime? BirthDate { get; set; }
        public DateTime? HireDate { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string PostalCode { get; set; }
    }

    [Serializable]
    public class EmployeeFilter 
    {
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string City { get; set; }
    }

    [Serializable]
    public class EmployeeList
    {
        public int ListCount(EmployeeFilter filter, string sortType, int startRowIndex, int maximumRows)
        {
            var rows = listQuery();
            return rows.Count();
        }

        public IEnumerable<EmployeeData> List(EmployeeFilter filter, string sortType, int startRowIndex, int maximumRows)
        {
            var rows = listQuery();
            if (!string.IsNullOrEmpty(sortType)) rows = listSort(rows, sortType);
            return (maximumRows > 0)
                ? rows.Distinct().Skip(startRowIndex).Take(maximumRows).ToList()
                : rows.Distinct().Skip(startRowIndex).ToList();
        }

        public IQueryable<EmployeeData> listQuery()
        {
            var dc = new NorthwindDataContext();
            var allrows = from emp in dc.Employees
                          select new EmployeeData()
                          {
                              EmployeeId = emp.EmployeeID,
                              ReportsToId = emp.ReportsTo,
                              FirstName = emp.FirstName,
                              LastName = emp.LastName,
                              Address = emp.Address,
                              City = emp.City,
                              PostalCode = emp.PostalCode,
                              BirthDate = emp.BirthDate,
                              HireDate = emp.HireDate,
                              Title = emp.Title,
                          };
            return allrows;
        }

        public IQueryable<EmployeeData> listSort(IQueryable<EmployeeData> rows, string sortType)
        {
            bool sortDescending = false;
            if (!string.IsNullOrEmpty(sortType))
            {
                string[] values = sortType.Split(' ');
                sortType = values[0];
                if (values.Length > 1)
                {
                    sortDescending = (values[1] == "DESC");
                }
            }


            if (!string.IsNullOrEmpty(sortType))
            {
                rows = rows.OrderBy(string.Format("{0}{1}",sortType,(sortDescending) ? " DESC" : ""));
            }

            return rows;
        }
    }
}

用户层:

<asp:ListView ID="lstEmployees" runat="server" DataSourceID="odsEmployees" >
    <LayoutTemplate>
        <table>
            <tr>
                <th align="left">
                    <asp:LinkButton runat="server" ID="LinkButton1" CommandName="Sort" CommandArgument="FirstName">First Name</asp:LinkButton>
                </th>
                <th align="left">
                    <asp:LinkButton runat="server" ID="LinkButton5" CommandName="Sort" CommandArgument="LastName">Last Name</asp:LinkButton>
                </th>
                <th align="left">
                    <asp:LinkButton runat="server" ID="LinkButton6" CommandName="Sort" CommandArgument="BirthDate">Birth Date</asp:LinkButton>
                </th>
            </tr>
            <asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
        </table>
    </LayoutTemplate>
    <ItemTemplate>
        <tr>
            <td><%#Eval("FirstName") %></td>
            <td><%#Eval("LastName") %></td>
            <td><%#string.Format("{0:d}", Eval("BirthDate"))%></td>
        </tr>
    </ItemTemplate>
    <EmptyDataTemplate>
        Sorry - no employees found
    </EmptyDataTemplate>
</asp:ListView>
<asp:ObjectDataSource ID="odsEmployees" runat="server" EnablePaging="True" OldValuesParameterFormatString="original_{0}"
    SelectCountMethod="ListCount" SelectMethod="List" SortParameterName="sortType"
    TypeName="BusinessLayer.EmployeeList">
    <SelectParameters>
        <asp:SessionParameter Name="filter" SessionField="employeeFilter" Type="Object" />
        <asp:Parameter Name="sortType" Type="String" />
        <asp:Parameter Name="startRowIndex" Type="Int32" />
        <asp:Parameter Name="maximumRows" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

分析: 我对此进行了详尽的测试。正在调用排序代码,并且从 List 方法返回的查询已正确排序;但是,表单上显示的数据未排序。

listSort 返回此 SQL 查询:

SELECT [t0].[EmployeeID] AS [EmployeeId], [t0].[ReportsTo] AS [ReportsToId], [t0].[LastName], [t0].[FirstName], [t0].[Title], [t0].[BirthDate], [t0].[HireDate], [t0].[Address], [t0].[City], [t0].[PostalCode]
FROM [dbo].[Employees] AS [t0]
ORDER BY [t0].[BirthDate] DESC 

进一步测试表明我使用 GridView 得到了相同的结果

Symptoms: ListView not sorting

Data Layer: Linq-generated class that includes Northwind Employee table and System.Linq.Dynamic class

Business Layer:

namespace BusinessLayer
{
    [Serializable]
    public class EmployeeData
    {
        public int EmployeeId { get; set; }
        public int? ReportsToId { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string Title { get; set; }
        public DateTime? BirthDate { get; set; }
        public DateTime? HireDate { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string PostalCode { get; set; }
    }

    [Serializable]
    public class EmployeeFilter 
    {
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string City { get; set; }
    }

    [Serializable]
    public class EmployeeList
    {
        public int ListCount(EmployeeFilter filter, string sortType, int startRowIndex, int maximumRows)
        {
            var rows = listQuery();
            return rows.Count();
        }

        public IEnumerable<EmployeeData> List(EmployeeFilter filter, string sortType, int startRowIndex, int maximumRows)
        {
            var rows = listQuery();
            if (!string.IsNullOrEmpty(sortType)) rows = listSort(rows, sortType);
            return (maximumRows > 0)
                ? rows.Distinct().Skip(startRowIndex).Take(maximumRows).ToList()
                : rows.Distinct().Skip(startRowIndex).ToList();
        }

        public IQueryable<EmployeeData> listQuery()
        {
            var dc = new NorthwindDataContext();
            var allrows = from emp in dc.Employees
                          select new EmployeeData()
                          {
                              EmployeeId = emp.EmployeeID,
                              ReportsToId = emp.ReportsTo,
                              FirstName = emp.FirstName,
                              LastName = emp.LastName,
                              Address = emp.Address,
                              City = emp.City,
                              PostalCode = emp.PostalCode,
                              BirthDate = emp.BirthDate,
                              HireDate = emp.HireDate,
                              Title = emp.Title,
                          };
            return allrows;
        }

        public IQueryable<EmployeeData> listSort(IQueryable<EmployeeData> rows, string sortType)
        {
            bool sortDescending = false;
            if (!string.IsNullOrEmpty(sortType))
            {
                string[] values = sortType.Split(' ');
                sortType = values[0];
                if (values.Length > 1)
                {
                    sortDescending = (values[1] == "DESC");
                }
            }


            if (!string.IsNullOrEmpty(sortType))
            {
                rows = rows.OrderBy(string.Format("{0}{1}",sortType,(sortDescending) ? " DESC" : ""));
            }

            return rows;
        }
    }
}

User Layer:

<asp:ListView ID="lstEmployees" runat="server" DataSourceID="odsEmployees" >
    <LayoutTemplate>
        <table>
            <tr>
                <th align="left">
                    <asp:LinkButton runat="server" ID="LinkButton1" CommandName="Sort" CommandArgument="FirstName">First Name</asp:LinkButton>
                </th>
                <th align="left">
                    <asp:LinkButton runat="server" ID="LinkButton5" CommandName="Sort" CommandArgument="LastName">Last Name</asp:LinkButton>
                </th>
                <th align="left">
                    <asp:LinkButton runat="server" ID="LinkButton6" CommandName="Sort" CommandArgument="BirthDate">Birth Date</asp:LinkButton>
                </th>
            </tr>
            <asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
        </table>
    </LayoutTemplate>
    <ItemTemplate>
        <tr>
            <td><%#Eval("FirstName") %></td>
            <td><%#Eval("LastName") %></td>
            <td><%#string.Format("{0:d}", Eval("BirthDate"))%></td>
        </tr>
    </ItemTemplate>
    <EmptyDataTemplate>
        Sorry - no employees found
    </EmptyDataTemplate>
</asp:ListView>
<asp:ObjectDataSource ID="odsEmployees" runat="server" EnablePaging="True" OldValuesParameterFormatString="original_{0}"
    SelectCountMethod="ListCount" SelectMethod="List" SortParameterName="sortType"
    TypeName="BusinessLayer.EmployeeList">
    <SelectParameters>
        <asp:SessionParameter Name="filter" SessionField="employeeFilter" Type="Object" />
        <asp:Parameter Name="sortType" Type="String" />
        <asp:Parameter Name="startRowIndex" Type="Int32" />
        <asp:Parameter Name="maximumRows" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

Analysis:
I have tested this exhaustively. The sort code is getting called and the query that gets returned from the List method is correctly sorted; however, the data displayed on the form is not sorted.

listSort is returning this SQL query:

SELECT [t0].[EmployeeID] AS [EmployeeId], [t0].[ReportsTo] AS [ReportsToId], [t0].[LastName], [t0].[FirstName], [t0].[Title], [t0].[BirthDate], [t0].[HireDate], [t0].[Address], [t0].[City], [t0].[PostalCode]
FROM [dbo].[Employees] AS [t0]
ORDER BY [t0].[BirthDate] DESC 

Further testing reveals that I get the same results with a GridView

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美男兮 2024-11-12 16:40:44

事实证明,对象数据源 (ODS) 不使用 IEnumerable 进行排序。 Linq 代码必须返回 DataTable 或 DataSet。我找到了两篇文章展示了如何做到这一点。其中一个已经接近但不完整。另一个像魔术一样起作用:
Linq To数据表

这是我在短短几分钟内找到并成功运行的代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;

namespace BusinessLayer
{
    public static class ConvertDataTable
    {
        public static DataTable ToTable<T>(this IEnumerable<T> varlist, CreateRowDelegate<T> fn)
        {

            DataTable dtReturn = new DataTable();
            // Could add a check to verify that there is an element 0

            T TopRec = varlist.ElementAt(0);

            // Use reflection to get property names, to create table

            // column names

            PropertyInfo[] oProps =
            ((Type)TopRec.GetType()).GetProperties();

            foreach (PropertyInfo pi in oProps)
            {

                Type colType = pi.PropertyType; if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                {

                    colType = colType.GetGenericArguments()[0];

                }

                dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
            }

            foreach (T rec in varlist)
            {

                DataRow dr = dtReturn.NewRow(); foreach (PropertyInfo pi in oProps)
                {
                    dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue(rec, null);
                }
                dtReturn.Rows.Add(dr);

            }

            return (dtReturn);
        }

        public delegate object[] CreateRowDelegate<T>(T t);
    }
}

这是新的 List 方法:

public DataTable List(EmployeeFilter filter, string sortType, int startRowIndex, int maximumRows)
{
    var rows = listQuery();
    if (!string.IsNullOrEmpty(sortType)) rows = listSort(rows, sortType).Skip(startRowIndex);
    if (maximumRows > 0) rows = rows.Take(maximumRows);
    DataTable dt = rows.ToTable(r => new object[] { rows });
    return dt;
}

Turns out that an Object Data Source (ODS) does not do sorting with an IEnumerable. The Linq code must return a DataTable or DataSet. I found two articles that showed how to do that. One was close but incomplete. The other worked like magic:
Linq To DataTable.

Here is the code that I found and managed to get working in just a few minutes:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;

namespace BusinessLayer
{
    public static class ConvertDataTable
    {
        public static DataTable ToTable<T>(this IEnumerable<T> varlist, CreateRowDelegate<T> fn)
        {

            DataTable dtReturn = new DataTable();
            // Could add a check to verify that there is an element 0

            T TopRec = varlist.ElementAt(0);

            // Use reflection to get property names, to create table

            // column names

            PropertyInfo[] oProps =
            ((Type)TopRec.GetType()).GetProperties();

            foreach (PropertyInfo pi in oProps)
            {

                Type colType = pi.PropertyType; if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                {

                    colType = colType.GetGenericArguments()[0];

                }

                dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
            }

            foreach (T rec in varlist)
            {

                DataRow dr = dtReturn.NewRow(); foreach (PropertyInfo pi in oProps)
                {
                    dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue(rec, null);
                }
                dtReturn.Rows.Add(dr);

            }

            return (dtReturn);
        }

        public delegate object[] CreateRowDelegate<T>(T t);
    }
}

And here is the new List method:

public DataTable List(EmployeeFilter filter, string sortType, int startRowIndex, int maximumRows)
{
    var rows = listQuery();
    if (!string.IsNullOrEmpty(sortType)) rows = listSort(rows, sortType).Skip(startRowIndex);
    if (maximumRows > 0) rows = rows.Take(maximumRows);
    DataTable dt = rows.ToTable(r => new object[] { rows });
    return dt;
}
陪你搞怪i 2024-11-12 16:40:44

老实说,我不知道 ListView 如何或是否可以与 ODS 一起使用。我只将 ListViews 与 LDS 一起使用,但我确实看到了一个可能的代码问题。如果你期待其中一个或另一个开火,你就不会明白。

if (!string.IsNullOrEmpty(sortType)) // why repeat the same 'if' statement logic?
{
     string[] values = sortType.Split(' ');
     sortType = values[0];
     if (values.Length > 1)
     {
         sortDescending = (values[1] == "DESC");
     }
}


if (!string.IsNullOrEmpty(sortType)) // why repeat the same 'if' statement logic?
{
    rows = rows.OrderBy(string.Format("{0}{1}",sortType,(sortDescending) ? " DESC" : ""));
}

I honestly don't know how or if a ListView will work with an ODS. I have only used ListViews with an LDS but I do see one possible code issue. If you are expecting one or the other here to fire, you won't get that.

if (!string.IsNullOrEmpty(sortType)) // why repeat the same 'if' statement logic?
{
     string[] values = sortType.Split(' ');
     sortType = values[0];
     if (values.Length > 1)
     {
         sortDescending = (values[1] == "DESC");
     }
}


if (!string.IsNullOrEmpty(sortType)) // why repeat the same 'if' statement logic?
{
    rows = rows.OrderBy(string.Format("{0}{1}",sortType,(sortDescending) ? " DESC" : ""));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文