EF LInq左外连接按拳头排序

时间:2016-01-21 16:32:45

标签: entity-framework linq sql-order-by

我有这个左外连接查询

var queryString = (from entity in _dbContext.Links
                   from translations in _dbContext.LinksTrs.Where(p => p.LinkId == entity.Id).OrderBy(p => p.LanguageCode).Take(1).DefaultIfEmpty()
                   select new LinksAdminListModel()
                   {
                     Id = entity.Id,
                     Name = (translations == null) ? "" : translations.Name,
                     Url = entity.Url,
                     Active = entity.Active
                   });

正如您所看到的,当我返回所有左行时,我从查询的右侧只得到一行。

我需要的是,只需通过LanguageCode进行排序,我需要先通过一个特定的LanguageCode告诉查询,然后再进行排序。

如果我加上这个:

.OrderBy(p => (p.LanguageCode == currentLanguage) ? 0 : 1)

其中currentLanguage只是一个包含语言“en”,“fr”的字符串...... 所以查询是:

var queryString = (from entity in _dbContext.Links
                   from translations in _dbContext.LinksTrs.Where(p => p.LinkId == entity.Id).OrderBy(p => (p.LanguageCode == currentLanguage) ? 0 : 1).Take(1).DefaultIfEmpty()
                   select new LinksAdminListModel()
                   {
                     Id = entity.Id,
                     Name = (translations == null) ? "" : translations.Name,
                     Url = entity.Url,
                     Active = entity.Active
                   });

我收到以下错误: “'where子句'中的未知列'Extent1.Id'”

我需要帮助,因为我需要返回当前语言(如果存在的话),如果不存在的话。

感谢。

修改

问题是ORDER与TAKE(1)的结合,但我确实只需要第一个......

编辑2

问题似乎是我上面评论的......这是我正在使用的查询:

            var queryString = (from entity in _dbContext.Links
                               from translations in _dbContext.LinksTrs.Where(p => p.LinkId == entity.Id).OrderByDescending(p => p.LanguageCode == currentLanguage).ThenBy(p => p.LanguageCode).Take(1)
                               select new LinksAdminListModel()
                               {
                                   Id = entity.Id,
                                   Name = (translations == null) ? "" : translations.Name,
                                   Url = entity.Url,
                                   Active = entity.Active
                               });

这就是它正在生成的SQL ......万一有人可以在这里看到一些东西:

SELECT
`Apply1`.`Id`, 
`Apply1`.`Name`, 
`Apply1`.`Url`, 
`Apply1`.`Active`
FROM (SELECT
`Extent1`.`Id`, 
`Extent1`.`OrderPos`, 
`Extent1`.`Url`, 
`Extent1`.`Active`, 
`Extent1`.`DateCreated`, 
`Extent1`.`DateModified`, 
`Extent1`.`UserIdModified`, 
(SELECT
`Project1`.`C1`
FROM (SELECT
CASE WHEN ((`Extent2`.`LanguageCode` = 'es-ES') OR   ((`Extent2`.`LanguageCode` IS  NULL) AND ('es-ES' IS  NULL))) THEN (1)  WHEN (NOT ((`Extent2`.`LanguageCode` = 'es-ES') AND ((CASE WHEN (`Extent2`.`LanguageCode` IS  NULL) THEN (1)  ELSE (0) END) = (CASE WHEN ('es-ES' IS  NULL) THEN (1)  ELSE (0) END)))) THEN (0) END AS `C1`, 
`Extent2`.`Name`, 
`Extent2`.`LanguageCode`
FROM `LinkTr` AS `Extent2`
 WHERE `Extent2`.`LinkId` = `Extent1`.`Id`) AS `Project1`
 ORDER BY 
`Project1`.`C1` DESC, 
`Project1`.`LanguageCode` ASC LIMIT 1) AS `C1`, 
(SELECT
`Project1`.`Name`
FROM (SELECT
CASE WHEN ((`Extent2`.`LanguageCode` = 'es-ES') OR ((`Extent2`.`LanguageCode` IS  NULL) AND ('es-ES' IS  NULL))) THEN (1)  WHEN (NOT ((`Extent2`.`LanguageCode` = 'es-ES') AND ((CASE WHEN (`Extent2`.`LanguageCode` IS  NULL) THEN (1)  ELSE (0) END) = (CASE WHEN ('es-ES' IS  NULL) THEN (1)  ELSE (0) END)))) THEN (0) END AS `C1`, 
`Extent2`.`Name`, 
`Extent2`.`LanguageCode`
FROM `LinkTr` AS `Extent2`
 WHERE `Extent2`.`LinkId` = `Extent1`.`Id`) AS `Project1`
 ORDER BY 
`Project1`.`C1` DESC, 
`Project1`.`LanguageCode` ASC LIMIT 1) AS `Name`, 
(SELECT
`Project1`.`LanguageCode`
FROM (SELECT
CASE WHEN ((`Extent2`.`LanguageCode` = 'es-ES') OR ((`Extent2`.`LanguageCode` IS  NULL) AND ('es-ES' IS  NULL))) THEN (1)  WHEN (NOT ((`Extent2`.`LanguageCode` = 'es-ES') AND ((CASE WHEN (`Extent2`.`LanguageCode` IS  NULL) THEN (1)  ELSE (0) END) = (CASE WHEN ('es-ES' IS  NULL) THEN (1)  ELSE (0) END)))) THEN (0) END AS `C1`, 
`Extent2`.`Name`, 
`Extent2`.`LanguageCode`
FROM `LinkTr` AS `Extent2`
 WHERE `Extent2`.`LinkId` = `Extent1`.`Id`) AS `Project1`
 ORDER BY 
`Project1`.`C1` DESC, 
`Project1`.`LanguageCode` ASC LIMIT 1) AS `LanguageCode`
   FROM `Link` AS `Extent1`) AS `Apply1`

编辑3

实体是:

public class Link : EntityBase
{
    public int OrderPos { get; set; }
    public string Url { get; set; }
    public bool Active { get; set; }

    public virtual IEnumerable<LinkTr> Translations { get; set; }
}

public class LinkTr : EntityBaseTr
{
    public string Name { get; set; }
    public string Summary { get; set; }

    //[ForeignKey("Link")]
    public int LinkId { get; set; }
    public virtual Link Link { get; set; }

    //[ForeignKey("Language")]
    public string LanguageCode { get; set; }
    public virtual Language Languages { get; set; }
}

public class EntityBase
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] //[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }

    public DateTime? DateCreated { get; set; }
    public DateTime? DateModified { get; set; }
    public int UserIdModified { get; set; }
}

public class EntityBaseTr
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public DateTime? DateCreated { get; set; }
}

1 个答案:

答案 0 :(得分:0)

不能与提供的信息重复。

我在测试过程中唯一注意到的是(translations == null) ? "" : translations.Name表达式null生成TranslationsId列,不确定是否有此类在你的实体。

无论如何,值得尝试以下替代方案,不包括这样的检查:

var queryString = (
    from entity in _dbContext.Links
    let translationName = _dbContext.LinksTrs
        .Where(p => p.LinkId == entity.Id)
        .OrderBy(p => p.LanguageCode == currentLanguage ? 0 : 1)
        .Select(p => p.Name)
        .FirstOrDefault();
    select new LinksAdminListModel()
    {
        Id = entity.Id,
        Name = translationName ?? "",
        Url = entity.Url,
        Active = entity.Active
     });

更新:

事实证明这是当前的MySql EF查询提供程序问题(bug?!)。

玩了一段时间后,我能够使其发挥作用的唯一方法如下

var queryString =
    (from entity in db.Links
     let translations = 
        db.LinksTrs.Where(p => p.LinkId == entity.Id && p.LanguageCode == currentLanguage).FirstOrDefault() ??
        db.LinksTrs.Where(p => p.LinkId == entity.Id).OrderBy(p => p.LanguageCode).FirstOrDefault()
     select new LinksAdminListModel
     {
         Id = entity.Id,
         Name = (translations == null) ? "" : translations.Name,
         Url = entity.Url,
         Active = entity.Active
     });