[英]LINQ Query to join 2 different tables
我目前正在从事图书馆管理项目,用户在借书时会更新他们的阅读状态。 当我使用 linq 连接表时,除了状态之外的所有其他内容都在那里。 这是我的模型: 用户模型(TblUser):
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
namespace LibMan.Models.DB
{
public partial class TblBookStatus
{
public int ResId { get; set; }
public string UserEmail { get; set; }
public int? BookId { get; set; }
public string Status { get; set; }
public virtual TblBook Book { get; set; }
public virtual TblUser User { get; set; }
}
}
图书模型(TblBook):
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace LibMan.Models.DB
{
public partial class TblBook
{
public int BookId { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public string Translator { get; set; }
public string Publisher { get; set; }
public string Description { get; set; }
public string Category { get; set; }
public byte[] Cover { get; set; }
}
}
图书状态模型(TblBookStatus):
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
namespace LibMan.Models.DB
{
public partial class TblBookStatus
{
public int ResId { get; set; }
public string UserEmail { get; set; }
public int? BookId { get; set; }
public string Status { get; set; }
public virtual TblBook Book { get; set; }
public virtual TblUser User { get; set; }
}
}
继续下面的代码,您可以看到我使用 linq 查询连接创建了 DisplayBook,但我无法在 html 端显示状态。 它说它
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LibMan.Models.DB;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
namespace LibMan.Pages
{
public class LibraryModel : PageModel
{
private readonly LibMan.Models.DB.LibManContext _context;
public string Message { get; set; }
public LibraryModel(LibMan.Models.DB.LibManContext context)
{
_context = context;
DisplayBook = new List<TblBook>();
; }
public IList<TblBookStatus> TblBookStatus { get; set; }
public IList<TblBook> TblBook { get; set; }
public IList<TblBook> DisplayBook { get; set; }
public IList<TblUser> TblUser{ get; set; }
[BindProperty]
public async Task OnGetAsync()
{
TblBookStatus = await _context.TblBookStatus.ToListAsync();
TblBook = await _context.TblBook.ToListAsync();
TblUser = await _context.TblUser.ToListAsync();
var UserEmail = HttpContext.Session.GetString("Email");
if (TblBookStatus != null && TblBook != null)
{
DisplayBook = (from book in TblBook
join stat in TblBookStatus
on book.BookId equals stat.BookId
join usr in TblUser
on stat.UserEmail equals usr.Email
where (usr.Email == UserEmail)
select book).ToList();
}
}
}
}
我怎样才能做到这一点? 我可以在将 DisplayBook 分配给 Linq 查询结果的语句中执行此操作吗? 做这个的最好方式是什么? 谢谢:注意。 如果需要,我可以提供 html 代码。
有多种选择。 您可以更正将DisplayBook
类型更改为 valuetuple 的代码(或创建单独的类型以提高可读性):
public IList<(TblBook Book, TblBookStatus Status)> DisplayBook { get; set; }
获取用户的书籍和状态:
TblBookStatus = await _context.TblBookStatus.Include(s => s.User).ToListAsync();
TblBook = await _context.TblBook.ToListAsync();
最后填写DisplayBook
:
DisplayBook = TblBook
.Select(b => (b, TblBookStatus.FirstOrDefault(s => s.BookId == b.BookId)))
.ToList()
据我从您的评论中了解到,您在状态和用户之间存在一对一的关系,所以这样您就可以获取图书馆中的所有书籍,并且所有状态(书籍的状态可以是null
)具有填充的用户关系。
附言
ToListAsync
不应返回 null,因此 null 检查在那里是多余的。
UPD
要仅获取有关一个用户及其书籍的信息,您可以使用单个查询来完成:
var statusesWithUserAndBooks = await _context.TblBookStatus
.Include(s => s.User)
.Include(s => s.Book)
.Where(s => s.User.Email == UserEmail)
.ToListAsync();
如果您需要数据子集,则使用必要的字段创建DTO
,如下所示:
public class DisplayBookDTO
{
public string Status { get; set; }
public string BookTitle { get; set; }
public string BookAuthor { get; set; }
}
public IList<DisplayBookDTO> DisplayBook { get; set; }
DisplayBook = await _context.TblBookStatus
.Where(s => s.User.Email == UserEmail
&& s.Book != null)
.Select(s => new DisplayBookDTO
{
Status = s.Status,
BookTitle = s.Book.Title,
BookAuthor = s.Book.Author
})
.ToListAsync();
无需单独查询每个表,然后加入。 让 LINQ 为您做。
var UserEmail = HttpContext.Session.GetString("Email");
var books = _context.TblBookStatus
.Where(
tbs => (tbs.Book != null && tbs.BookId == tbs.Book.BookId) &&
(tbs.User != null && tbs.UserEmail == tbs.User.Email) &&
tbs.UserEmail == UserEmail)
.Select(tbs => tbs.Book);
因为您在 EF 模型中定义了导航属性(使用虚拟属性),所以将自动为您完成连接。 在上面的例子中,我设置了 tbs.BookId == tbs.Book.BookId。 如果您在实体类型配置中定义了外键,则不需要这样做。 您也可以使用 EF 模型中的属性来定义这些关系。
例子:
[ForeignKey("BookId")]
public virtual TblBook Book { get; set; }
编辑:分解您需要返回的内容:
var books = _context.TblBookStatus
.Where(
tbs => (tbs.Book != null && tbs.BookId == tbs.Book.BookId) &&
(tbs.User != null && tbs.UserEmail == tbs.User.Email) &&
tbs.UserEmail == UserEmail)
.Select(tbs => new {
Status = tbs.Status,
BookName = tbs.Book.Name
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.