是否可以使用 "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
以下代码有效,但需要先从数据库中获取结果:
// 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