是否可以使用 "Array.IndexOf" 或其他代码派生数据对数据库中的 EF 查询结果进行排序?

Is is possible to sort EF query results in the database using "Array.IndexOf" or other code-derived data?

以下代码有效,但需要先从数据库中获取结果:

// ID's by priority (arbitrary yet limited number; eg. 1 to 10 values)
var ids = new [] { 3, 1, 2 };

// Should return "item 3" if it exists, else "item 1", else "item 2"..
var firstItemByPriority = context.Items
    .Where(i => ids.Contains(i.Id))
    .ToList() // materialize DB results
    .OrderBy(i => Array.IndexOf(ids, i.Id))
    .FirstOrDefault(); // ie. TOP 1 / LIMIT 1 / First (by ordering)

有没有一种方法可以在生成的数据库查询中进行排序? (当手动编写 SQL 时,可以用几种不同的方式构造。)

虽然上面的示例使用 Array.IndexOf,但总体目标是按派生数据 不在数据库中 进行排序。使用 SQL 服务器特定扩展 and/or 第三方扩展是公平的。

如果没有原始 SQL 查询,就无法有效地执行此操作,并且原始 SQL 查询无法与 EF6 中的 LINQ 查询组合,就像它们在 EF Core 中一样。但是 SQL 的查询非常简单。所以像这样:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Linq;

namespace Ef6Test
{

    public class Item
    {
        public int Id { get; set; }
        public String Name { get; set; }

    }


    public class Db : DbContext
    {
        public Db() : base("server=localhost;database=ef6Test;integrated security=true")
        { }
        public DbSet<Item> Items{ get; set; }
        
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Item>()
                        .ToTable("Items")
                        .Property(i => i.Id)
                        .HasColumnName("Id")
                        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

            base.OnModelCreating(modelBuilder);
        }


    }

    internal class Program
    {

        public static void Main(string[] args)
        {

            using (var db = new Db())
            {
                db.Database.Log = m => Console.WriteLine(m);

                if (db.Database.Exists())
                    db.Database.Delete();

                db.Database.Create();

                for (int i = 0; i < 1000; i += 2)
                {
                    var item = new Item() { Id = i, Name = $"Item{i}" };
                    db.Items.Add(item);
                    if (i % 100 == 0)
                        db.SaveChanges();

                }
                db.SaveChanges();

            }

            using (var db = new Db())
            {
                db.Database.Connection.Open();

                db.Database.ExecuteSqlCommand("create table #ids(position int primary key, id int)");

                var ids = new[] { 3, 1, 12, 5, 8, 10, 7};
                var json = System.Text.Json.JsonSerializer.Serialize(ids);

                var pIds = new SqlParameter("@ids", System.Data.SqlDbType.NVarChar, -1);
                pIds.Value = json;

                db.Database.ExecuteSqlCommand("insert into #ids(position,id) select [key], [value] from openjson(@ids)", pIds);

                var sql = @"
select top (@count) i.*
from Items i
join #ids ids
  on i.Id=ids.Id
order by ids.position
";
                var pCount = new SqlParameter("@count", 3);
                var results = db.Database.SqlQuery<Item>(sql,pCount).ToList();
                
                foreach (var item in results)
                {
                    Console.WriteLine(item.Id);
                }
              
            }
            Console.WriteLine("complete");
         }
  
        }
    }

产出

12
8
10
complete