c# - LINQ外连接动态OrderBy

标签 c# linq linq-to-sql gridview linqdatasource

在如下所示的 Linq 语句中(缩小到问题的相关部分):

var sites = from s in DataContext.Sites
            join add in DataContext.Address 
              on s.PrimaryAddress equals add into sa
    from a in sa.DefaultIfEmpty()
            select new {
                        s.Id,
                        s.SiteName,
                        PrimaryAddress = a
                       };

我们遇到的问题是,最终基于 GridView/LinqDataSource 组合的控件无法在 PrimaryAddress 连接类上正确排序(忽略它)。我们看到所有加入的类都有同样的行为。 GridView 有什么办法可以处理这个问题吗? 或者,是否有一种方法可以通过表达式在动态 OrderBy 的代码中处理它?<​​/strong>

附加说明:添加 .OrderBy(s => s.PrimaryAddress) 时,我们得到 Cannot order by type 'Address',当执行 .OrderBy( gs => gs.PrimaryBusinessAddress.AddressLine1) 我们得到 Specified method is not supported. 当对 LinqDataSource.OrderBy 本身进行排序时,为时已晚...它只对记录进行排序在当前页面上,而不是在整个页面上。

为清楚起见,这是网格中地址的格式:

public partial class Address
{
  public override string ToString()
  {
    return string.Format("{0} {1}{2} {3}",
    AddressLine1,
    City,
    !string.IsNullOrEmpty(State) && State != "None" ? ", " + State : string.Empty,
    !string.IsNullOrEmpty(Country) ? string.Format("({0})", Country) : string.Empty);
  }
}

如果我们可以按 AddressLine1 + City + State + Country 排序,那就足够了,但我不确定如何通过表达式树来做到这一点......无论 OrderBy我们通过表达式指定,它恢复为按 s.SiteName 排序(网格上的默认排序)。在我们的网格控件中显示的此类连接类的数量非常有限,每个类都有一个开关和表达式案例根本不是问题。对解决方案或完全不同的方法有任何想法吗?

最佳答案

我习惯于在代码中使用 LINQ to Entities,但我在 LINQPad 中经常使用 LINQ to SQL,以至于我已经相当熟悉它了。我不是完全确定我理解您遇到困难的地方,但我认为以下方法应该可行:

var sites = from s in DataContext.Sites
            orderby s.PrimaryAddress.AddressLine1,
                     s.PrimaryAddress.City,
                     s.PrimaryAddress.State,
                     s.PrimaryAddress.Country
            select new 
            {
                s.Id,
                s.SiteName,
                s.PrimaryAddress
            };

如果有什么我不明白的地方,请告诉我。

更新

我不确定为什么这对您不起作用。我刚刚在 LINQPad(LINQ to SQL 模式)中做了以下操作:

from p in person
orderby p.clue_type.clue_type_id,
        p.clue_type.clue_type
select new
{
    p.person_id, p.clue_type
}

所有结果的 clue_type = null。 LINQ to SQL 仅将空引用视为具有全空属性的值。这是生成的 SQL:

SELECT TOP (10) [t0].[person_id], [t2].[test], [t2].[clue_type_id], [t2].[clue_type]
FROM [person] AS [t0]
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[clue_type_id], [t1].[clue_type]
    FROM [clue_types] AS [t1]
    ) AS [t2] ON [t2].[clue_type_id] = [t0].[clue_type_id]
ORDER BY [t2].[clue_type_id], [t2].[clue_type]

注意 LEFT OUTER JOIN。这不会满足您的要求吗?

更新2

使查询动态化可能相当困难,具体取决于您使其动态化的程度。如果您希望能够根据传递到您的方法中的字符串值按要返回的任何属性进行排序,这是一个解决方案:

public class SiteDisplayInfo
{
    public int Id {get;set;}
    public string SiteName {get;set;}
    public string PrimaryAddress {get;set;}

    public static readonly Dictionary<string, Func<IQueryable<Site>, IOrderedQueryable<Site>>> OrderByFuncs = 
    new Dictionary<string, Func<IQueryable<Site>, IOrderedQueryable<Site>>>
    {
        {"Id", q => q.OrderBy(s => s.Id)},
        {"SiteName", q => q.OrderBy(s => s.SiteName)},
        {"PrimaryAddress", 
        q => q.OrderBy(s => s.PrimaryAddress.AddressLine1)
                             .ThenBy(s => s.PrimaryAddress.City)}
    };
}

...

public IEnumerable<SiteDisplayInfo> GetSites(string orderByString)
{
    IQueryable<Site> sites = DataBase.Sites;
    if (orderByString != null && SiteDisplayInfo.OrderByFuncs.ContainsKey(orderByString))
    {
        sites = SiteDisplayInfo.OrderByFuncs[orderByString](sites);
    }
    var query = from s in sites
                select new SiteDisplayInfo
                {
                    Id = s.Id,
                    SiteName = s.SiteName,
                    PrimaryAddress = s.PrimaryAddress.AddressLine1 + s.PrimaryAddress.City
                };
    return query.ToList();
}

还有一些其他方法可以做类似的事情,但这给了你一个大概的想法。

关于c# - LINQ外连接动态OrderBy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1476973/

相关文章:

linq - LINQ for LIKE查询数组元素

c# - 'CompanyName.Foo' 是一个 'namespace' 但像 'type' 一样使用

c# - 您可以强制 Parallel.Invoke 使用多线程吗?

c# - 使用 key A 和 B 读取 Mifare 1k 卡

c# xml 显示最高值

c# - Linq 外键 |如何只显示具有特定外键的元素?

c# - 为什么 OfType<> 比 Cast<> 快?

C#:从枚举到类的自动转换

c# - LINQ 查询来过滤数据?

visual-studio - 是什么导致 Visual Studio 无法正确加载程序集?