Here is a mad way to do it but it doesn't fall back to IEnumerable
var db = new BloggingContext();
var list = (new List<string> { "FR", "EN" }).
Select((s,i)=> $"select '{s}' as {nameof(OrderIndex.Name)},{i} as {nameof(OrderIndex.Id)}");
var order = db.Set<OrderIndex>().FromSql(String.Join(" union ",list));
var orderedItems = from post in db.Posts
join ln in order on post.Lang equals ln.Name into lnPost
from od in lnPost.DefaultIfEmpty()
orderby od.Id
select post;
var data = orderedItems.ToList();
You can find the definition of the BloggingContext here I just added a Lang field for a language code. This will work in SQLite, SqlServer and MySQL for oracle you need to add from dual
Due to how terrible EF core is you will need to go true the same procedure for OrderIndex as you would with an SQL view. In EF 6 there is a much nicer way of doing this with SqlQuery and you don't need to do the registration like with EF core.
The created query is
SELECT "post"."PostId", "post"."BlogId", "post"."Content", "post"."Date", "post"."Lang", "post"."Title", "ln"."Id", "ln"."Name"
FROM "Posts" AS "post"
LEFT JOIN (
select 'FR' as Name,0 as Id union select 'EN' as Name,1 as Id
) AS "ln" ON "post"."Lang" = "ln"."Name"
ORDER BY "ln"."Id", "post"."Lang"
EDIT:
Just remembered a different way to do it it's not as mad but might be better.
var lang = new List<string> { "FR", "EN" };
var orderedItems = from post in db.Posts
orderby (lang[0] == post.Lang) ?
0 :((lang[1] == post.Lang) ? 1 : 2)
select post;
var param = Expression.Parameter(typeof(Post));
var order = lang.Select((s, i) => new { s, i })
.Aggregate((Expression)Expression.Constant(lang.Count), (agg, i) =>
Expression.Condition(
Expression.Equal(Expression.Property(param,nameof(Post.Lang)),
Expression.Constant(i.s)),
Expression.Constant(i.i),
agg));
var exp = Expression.Lambda<Func<Post, int>>(order, param);
var data = db.Posts.OrderBy(exp).ToList();
And the SQL
SELECT "p"."PostId", "p"."BlogId", "p"."Content", "p"."Date", "p"."Lang", "p"."Title"
FROM "Posts" AS "p"
ORDER BY CASE
WHEN "p"."Lang" = 'EN'
THEN 1 ELSE CASE
WHEN "p"."Lang" = 'FR'
THEN 0 ELSE 2
END
END
I still think the mad way is useful for something I just don't know what.