1

I have this left outer join query

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

As you can see I'm getting just one row from the right side of the query while I return all the left rows.

What I need is, instead sorting just by LanguageCode, I need to tell the query to sort by a specifid LanguageCode first and then the rest.

If I add this:

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

where currentLanguage is just a string containing the language "en", "fr"... so the query is:

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

I get the following error: "Unknown column 'Extent1.Id' in 'where clause'"

I need help since I need to return the current language if it exists, if not the next one.

Thanks.

EDIT

The problem is the combination of the ORDER with the TAKE(1), but I do need to take just the first one...

EDIT 2

The probelm seems to be what I commented above...this is the query I'm using:

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

And this is the SQL it is generating...in case someone can see something in here:

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`

EDIT 3

The entities are:

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; }
}
John Mathison
  • 904
  • 1
  • 11
  • 36
  • "I need help since I need to return the current language if it exists, if not the next one." So if you don't find a matching translation, you just take the translation of _any_ other LanuageCode? – Markus Weninger Jan 21 '16 at 17:09
  • Yes, first the current one and if it doesn't existe I take any other...if I just order the LanguageCode it works, the problem is when I try to force the current one to be the first one – John Mathison Jan 21 '16 at 17:14
  • The only question I could find regarding Extent1.Id is [this one](http://stackoverflow.com/questions/26948688/column-extent1-id-does-not-exist-in-mono-with-entity-framework-6-and-postgresql). But you say that it work before with Id... Hmm... – Markus Weninger Jan 21 '16 at 17:16
  • that is not my case....thanks – John Mathison Jan 21 '16 at 17:36

1 Answers1

0

Cannot duplicate with the information provided.

The only thing I've noticed during the testing was that the expression (translations == null) ? "" : translations.Name was generating null check for Translations table Id column, not sure if you have such in your entity.

In any case, it's worth trying the following alternative which does not include such a check:

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

UPDATE:

It turns out that this is a current MySql EF query provider issue (bug?!).

After playing a while, the only way I was able to make it work is as follows

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
     });
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • Same result. Not working. I think it has something to do with the fact that even a simple order is not working...(see my edit) – John Mathison Jan 22 '16 at 08:58
  • If I run your solution in my ASP MVC EF project I get: "The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'." BUT if I run the resultant SQL in a SQL client I'm getting the same error message "Unknown column 'Extent1.Id' in 'where clause'" – John Mathison Jan 22 '16 at 09:02
  • As I mentioned, I've tried both your queries and mine in the latest EF6 and all they work w/o any problem. What 's the Entity Framework version you are using? – Ivan Stoev Jan 22 '16 at 09:06
  • I'm using ASP.NET MVC EF6, and the database is MySQL. We are working CodeFirst. The problem is the combination of the Take(1) with the Order... – John Mathison Jan 22 '16 at 09:32
  • Same result for your solution...if I remove the TAKE(1) argument or the ORDERBY it works, but it is not what I need... – John Mathison Jan 22 '16 at 09:35
  • I have updated my answer with the query I'm using and the SQL it is obtaining...the same error "Unknown column 'Extent1.Id' in 'where clause'" – John Mathison Jan 22 '16 at 09:54
  • If it is working for you, how did you create the entities? Please send me the entities you have created in case that's the difference.... – John Mathison Jan 22 '16 at 10:29
  • One of the differences is that I test in SQL Server. The entities I've created are extracted from your post. The only thing which was unclear is what's the primary key of `LinkTranslation`, so I've just added a standard `int Id { get; set; }`. Why don't you post your entities so I can check at least if the problem is MySQL related. – Ivan Stoev Jan 22 '16 at 10:42
  • Yes, thanks. I just EDIT my question to add the entities (EDIT 3) – John Mathison Jan 22 '16 at 12:58
  • @MikeJohnson Confirming. Does not happen on SqlServer (also a totally different SQL query), **does** happen on MySql :( – Ivan Stoev Jan 22 '16 at 16:00
  • So you think is a mysql issue? Well now I don't know what to do since we do need this query for many things... – John Mathison Jan 22 '16 at 16:56
  • It doesn't work...it seems like a MySQL bug. We are thinking to go to MSSQL since this is causing us too many problemas. Is it better using EF LINQ with MSSQL than MySQL? (Never used MSSQL before) – John Mathison Jan 23 '16 at 20:13
  • Don't say you use a older version of MySQL because I specifically installed MySQL (the latest, I've never used that before) to check this issue and the updated version really works with that. I have no complaints with SqlServer. – Ivan Stoev Jan 23 '16 at 21:30
  • What do you mean? I have the latest version of mysql and it doesn't work. Also we are realizing some queries that work on mssql don't in mysql. Also the performance of the generated sql is much better for mssql with EF6. We are realizing that using EF6 we do have a problem with Mysql... – John Mathison Jan 23 '16 at 23:21
  • What I'm saying is that the variant of the query included in the **UPDATE** section of my answer **does** successfully run on MySQL, thus I assume it works. I have no more ideas what or why it doesn't work for you. – Ivan Stoev Jan 23 '16 at 23:55