C# 实体框架-选定条目上的嵌套选择查询

C# 实体框架-选定条目上的嵌套选择查询,c#,asp.net,entity-framework,asp.net-core,entity-framework-core,C#,Asp.net,Entity Framework,Asp.net Core,Entity Framework Core,我正在使用。我的模特就像- public class Review { [Key, Required] public Guid Id { get; set; } public int Rating { get; set; } public DateTime WatchDate { get; set; } public virtual Guid UserId { get; set; } public virtual User User { get

我正在使用。我的模特就像-

public class Review
{
    [Key, Required]
    public Guid Id { get; set; }

    public int Rating { get; set; }
    public DateTime WatchDate { get; set; }

    public virtual Guid UserId { get; set; }
    public virtual User User { get; set; }
}
我的控制器是这样的-

public async Task<IActionResult> Index()
{
    var data = await _context.Reviews
                        .Include(r=>r.User)
                        .Select(r => new Review {
                            Id = r.Id,
                            WatchDate = r.WatchDate,
                            User = r.User,
                            Rating = r.Rating
                        })
                        .OrderByDescending(r => r.Rating)
                        .ToListAsync();
    return View(data);
}
公共异步任务索引()
{
var data=wait_context.Reviews
.Include(r=>r.User)
.选择(r=>new Review{
Id=r.Id,
WatchDate=r.WatchDate,
User=r.User,
额定值=r.额定值
})
.OrderByDescending(r=>r.Rating)
.ToListAsync();
返回视图(数据);
}
它做得很好,但是它像这样查询
用户
表的所有数据(红色标记区域)-

但是我只需要
电子邮件
,所以我只想从中选择电子邮件(黄色标记的)。我在上层执行
Select
,但在内部元素中不能执行相同的操作。据我所知,在实体框架中有一种类似的方法。但代码在版本更改时不起作用

谁能帮忙,我怎样才能完成

如何在列表中仅包含用户电子邮件,而不包括所有数据?那么如何选择嵌套条目呢?

请尝试下一步:

var data = await _context.Reviews
                    .OrderByDescending(r => r.Rating)
                    .Select(r => new Review {
                        Id = r.Id,
                        WatchDate = r.WatchDate,
                        User = new User { Email = r.User.Email},
                        Rating = r.Rating
                    })                       
                    .ToListAsync();
但我认为更好的设计是创建特定的
DTO
,它只包含所需的属性,并将其填入
Select
子句中

另外
.Include(r=>r.User)
调用是不需要的,因为您有
Select
子句。

请尝试下一步:

var data = await _context.Reviews
                    .OrderByDescending(r => r.Rating)
                    .Select(r => new Review {
                        Id = r.Id,
                        WatchDate = r.WatchDate,
                        User = new User { Email = r.User.Email},
                        Rating = r.Rating
                    })                       
                    .ToListAsync();
但我认为更好的设计是创建特定的
DTO
,它只包含所需的属性,并将其填入
Select
子句中


另外,
.Include(r=>r.User)
调用是不需要的,因为您有
Select
子句。

您需要在dto(数据传输对象)中映射您的实体,该dto具有完全相同的字段,更少的用户,其中您仅添加为参数的UserEmail

public async Task<IActionResult> Index()
{
    var data = await _context.Reviews
                        .Include(r=>r.User)
                        .Select(r => new Dtos.Review {
                            Id = r.Id,
                            WatchDate = r.WatchDate,
                            UserEmail = r.User.Email,
                            Rating = r.Rating
                        })
                        .OrderByDescending(r => r.Rating)
                        .ToListAsync();
    return View(data);
}
Dto:


您需要将实体映射到dto(数据传输对象)中,该dto具有完全相同的字段,更少的用户,其中您添加为仅参数的UserEmail

public async Task<IActionResult> Index()
{
    var data = await _context.Reviews
                        .Include(r=>r.User)
                        .Select(r => new Dtos.Review {
                            Id = r.Id,
                            WatchDate = r.WatchDate,
                            UserEmail = r.User.Email,
                            Rating = r.Rating
                        })
                        .OrderByDescending(r => r.Rating)
                        .ToListAsync();
    return View(data);
}
Dto:

作为一个例子,我建议,它只包含必要的数据,而不包含数据库对象:

public class UserReviewDTO
{
    public Guid Id { get; set; }
    public int Rating { get; set; }
    public DateTime WatchDate { get; set; }
    public string UserEmail { get; set; }
}
您可以这样进行查询:

var data = await _context.Reviews
    .Select(r => new UserReviewDTO {
        Id = r.Id,
        WatchDate = r.WatchDate,
        UserEmail = r.User.Email,
        Rating = r.Rating
    })
    .OrderByDescending(r => r.Rating)
    .ToListAsync();
作为一个例子,我建议,它只包含必要的数据,而不包含数据库对象:

public class UserReviewDTO
{
    public Guid Id { get; set; }
    public int Rating { get; set; }
    public DateTime WatchDate { get; set; }
    public string UserEmail { get; set; }
}
您可以这样进行查询:

var data = await _context.Reviews
    .Select(r => new UserReviewDTO {
        Id = r.Id,
        WatchDate = r.WatchDate,
        UserEmail = r.User.Email,
        Rating = r.Rating
    })
    .OrderByDescending(r => r.Rating)
    .ToListAsync();

对于视图,最好使用
ViewModel
。因此,首先,创建一个
ViewModel
类,如下所示:

public class ReviewViewModel
{
    public Guid Id { get; set; }

    public int Rating { get; set; }
    public DateTime WatchDate { get; set; }

    public Guid UserId { get; set; }
    public string UserEmail { get; set; }
}
public async Task<IActionResult> Index()
{
    var data = await _context.Reviews
                        .Select(r => new ReviewViewModel {
                            Id = r.Id,
                            WatchDate = r.WatchDate,
                            Rating = r.Rating,
                            UserId = r.User.Id,
                            UserEmail = r.User.Email,
                        })
                        .OrderByDescending(r => r.Rating)
                        .ToListAsync();
    return View(data);
}
然后将查询投影到
ViewModel
类型,如下所示:

public class ReviewViewModel
{
    public Guid Id { get; set; }

    public int Rating { get; set; }
    public DateTime WatchDate { get; set; }

    public Guid UserId { get; set; }
    public string UserEmail { get; set; }
}
public async Task<IActionResult> Index()
{
    var data = await _context.Reviews
                        .Select(r => new ReviewViewModel {
                            Id = r.Id,
                            WatchDate = r.WatchDate,
                            Rating = r.Rating,
                            UserId = r.User.Id,
                            UserEmail = r.User.Email,
                        })
                        .OrderByDescending(r => r.Rating)
                        .ToListAsync();
    return View(data);
}
公共异步任务索引()
{
var data=wait_context.Reviews
.选择(r=>new ReviewViewModel{
Id=r.Id,
WatchDate=r.WatchDate,
额定值=r.额定值,
UserId=r.User.Id,
UserEmail=r.User.Email,
})
.OrderByDescending(r=>r.Rating)
.ToListAsync();
返回视图(数据);
}

视图最好使用
ViewModel
。因此,首先,创建一个
ViewModel
类,如下所示:

public class ReviewViewModel
{
    public Guid Id { get; set; }

    public int Rating { get; set; }
    public DateTime WatchDate { get; set; }

    public Guid UserId { get; set; }
    public string UserEmail { get; set; }
}
public async Task<IActionResult> Index()
{
    var data = await _context.Reviews
                        .Select(r => new ReviewViewModel {
                            Id = r.Id,
                            WatchDate = r.WatchDate,
                            Rating = r.Rating,
                            UserId = r.User.Id,
                            UserEmail = r.User.Email,
                        })
                        .OrderByDescending(r => r.Rating)
                        .ToListAsync();
    return View(data);
}
然后将查询投影到
ViewModel
类型,如下所示:

public class ReviewViewModel
{
    public Guid Id { get; set; }

    public int Rating { get; set; }
    public DateTime WatchDate { get; set; }

    public Guid UserId { get; set; }
    public string UserEmail { get; set; }
}
public async Task<IActionResult> Index()
{
    var data = await _context.Reviews
                        .Select(r => new ReviewViewModel {
                            Id = r.Id,
                            WatchDate = r.WatchDate,
                            Rating = r.Rating,
                            UserId = r.User.Id,
                            UserEmail = r.User.Email,
                        })
                        .OrderByDescending(r => r.Rating)
                        .ToListAsync();
    return View(data);
}
公共异步任务索引()
{
var data=wait_context.Reviews
.选择(r=>new ReviewViewModel{
Id=r.Id,
WatchDate=r.WatchDate,
额定值=r.额定值,
UserId=r.User.Id,
UserEmail=r.User.Email,
})
.OrderByDescending(r=>r.Rating)
.ToListAsync();
返回视图(数据);
}

您可以这样做。Select(p=>new{p.User.Email}).AsEnumerable()如果使用Select而不使用Include,则用户将为空。您可以这样做。Select(p=>new{p.User.Email})。AsEnumerable()如果使用Select而不使用Include,则用户将为Null您不需要编写
r.User!=无效的r、 User.Email:null,
。EF Core将在生成SQL之前执行必要的操作。谢谢。答案已更新。对于我来说,这是一个很好的解决方案,可以防止空值错误。我太悲观了:)你不需要写
r.User!=无效的r、 User.Email:null,
。EF Core将在生成SQL之前执行必要的操作。谢谢。答案已更新。对于我来说,这是一个很好的解决方案,可以防止空值错误。我太悲观了:))