我想获取类别中包含最新产品的类别列表。
我正在使用Entity Framework Core 2.1。
我已经尝试过了,但是速度很慢
var categories = context.Categories.Select(x => new {
x.Id,
Product = x.Products.OrderByDescending(y => y.Date).Select(y => y.Name).FirstOrDefault()
}
答案 0 :(得分:1)
该LINQ查询应该生成单个SQL查询,该查询应该很快。
类似的东西:
SELECT [t].[CategoryId], (
SELECT TOP(1) [r].[Name]
FROM [Products] AS [r]
WHERE [t].[CategoryId] = [r].[CategoryId]
ORDER BY [r].[Date] DESC
) AS [FirstName]
FROM [Categorys] AS [t]
这里有一个包含100个类别的样本,每个类别有1000种要测试的产品。代码优先将在Product.CategoryId上创建索引,但是即使没有索引,这也不是昂贵的查询。
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
namespace EfCoreTest
{
public class Category
{
public int CategoryId { get; set; }
public virtual ICollection<Product> Readings { get; } = new HashSet<Product>();
}
public class Product
{
public int ProductId{ get; set; }
public string Name { get; set; }
public DateTime Date { get; set; }
public Category Category { get; set; }
}
public class Db : DbContext
{
public DbSet<Category> Categorys { get; set; }
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.;database=EfCoreTest;Integrated Security=true");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
class Program
{
static void Main(string[] args)
{
using (var db = new Db())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
for (int i = 0; i < 100; i++)
{
var t = new Category();
for (int j = 0; j < 1000; j++)
{
var product = new Product()
{
Category = t,
Date = DateTime.Now,
Name = $"Category {j}{i}"
};
db.Add(product);
}
db.Add(t);
}
db.SaveChanges();
}
using (var db = new Db())
{
var q = db.Categorys.Select(t => new
{
t.CategoryId,
FirstName = t.Readings.OrderByDescending(r => r.Date).Select(r => r.Name).FirstOrDefault()
});
var l = q.ToList();
Console.WriteLine("Hit any key to exit.");
Console.ReadKey();
}
}
}
}