c# - Linq - 在包含中排序

标签 c# entity-framework linq asp.net-core

我遇到需要为 Include 对象完成 OrderBy 的情况。到目前为止,这是我尝试过的方式

Customers query = null;

try
{
    query = _context.Customers
        .Include(x => x.CustomerStatus)
        .ThenInclude(x => x.StatusNavigation)
        .Select(x => new Customers()
        {
            Id = x.Id,
            Address = x.Address,
            Contact = x.Contact,
            Name = x.Name,
            CustomerStatus = new List<CustomerStatus>
            {
                x.CustomerStatus.OrderByDescending(y => y.Date).FirstOrDefault()
            }
        })
        .FirstOrDefault(x => x.Id == 3);
}
catch (Exception ex)
{
    throw;
}

上面的代码成功地对 include 元素进行了排序,但它不包括它的子表。 例如:Customer 包括 CustomerStatus,但 CustomerStatus 不包括 StatusNavigation 表。

我什至试过这个,但它都帮不了我

_context.Customers
    .Include(x => x.CustomerStatus.OrderByDescending(y => y.Date).FirstOrDefault())
    .ThenInclude(x => x.StatusNavigation).FirstOrDefault(x => x.Id == 3);

我做错了什么请指导我

连我都这样试过

var query = _context.CustomerStatus
    .GroupBy(x => x.CustomerId)
    .Select(x => x.OrderByDescending(y => y.Date).FirstOrDefault())
    .Include(x => x.StatusNavigation)
    .Join(_context.Customers, first => first.CustomerId, second => second.Id, (first, second) => new Customers
    {
        Id = second.Id,
        Name = second.Name,
        Address = second.Address,
        Contact = second.Contact,
        CustomerStatus = new List<CustomerStatus> {
            new CustomerStatus
            {
                Id = first.Id,
                CustomerId = first.CustomerId,
                Date = first.Date,
                StatusNavigation = first.StatusNavigation
            }
        },
    }).FirstOrDefault(x => x.Id == 3);

但这是访问数据库 3 次并在内存中过滤结果。 首先从客户状态中选择所有数据,然后从状态中选择所有数据,然后从客户中选择所有数据,然后过滤内存中的所有数据。还有其他有效的方法吗??

这是我准备的实体类 enter image description here

最佳答案

正如@Chris Pratt 提到的,一旦您在选择中执行新客户,您就在创建一个新模型。您正在丢弃 EntityFramework 构建的模型。我的建议是只查询:

query = _context.Customers
    .Include(x => x.CustomerStatus)
    .ThenInclude(x => x.StatusNavigation);

像这样,您将拥有一个 IQueryable 对象,除非您从中进行选择,否则它不会被执行:

var customer3 = query.FirstOrDefault(x=>x.Id==3)

返回客户和相互链接的表(CustomerStatus 和 StatusNavigation)。然后你可以创建你想要的对象:

var customer = new Customers()
    {
        Id = customer3.Id,
        Address = customer3.Address,
        Contact = customer3.Contact,
        Name = x.Name,
        CustomerStatus = new List<CustomerStatus>
        {
            customer3.CustomerStatus.OrderByDescending(y => y.Date).FirstOrDefault()
        }
    })

通过这种方式,您可以重用查询来创建不同的响应对象,并对数据库进行一次查询,但缺点是使用的内存比原始查询多(尽管这应该不是什么大问题) .

如果最初从数据库返回的模型不符合要求(即您总是需要这样做:CustomerStatus = new List {...}),则可能表明数据库模式没有很好地满足应用程序的需求,因此可能需要重构。

关于c# - Linq - 在包含中排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58102597/

相关文章:

c# - 包含数字 .ToString() 格式的 HTML

mysql - 当我尝试使用 MySQL 中的身份存储注册用户时出错

javascript - 将行添加到 ASP.NET MVC 表时更新连接的数据库表

linq - 用于多个edmx文件的Linq-To-Entities连接字符串

c# - LINQ to Entities 无法识别方法 'System.String GetMonthName(Int32)' 方法

c# - 如何在 Visio C# 中编写 Shape 的属性?

c# - 如何使用数据绑定(bind)更新 C# 图表控件

sql-server - 通过声明枚举会导致 HttpException SqlException

asp.net - LINQ:不支持查询运算符 'ElementAtOrDefault'

c# - 在 MVC3 中的每个 Action 之前运行一个方法