+-

我目前正在做一个图书馆管理项目,当用户借书时,会更新他们的阅读状态。当我使用linq来连接表时,除了状态之外,其他的都在那里.下面是我的模型:User模型(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; }
}
}
Book Model(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代码。
1
投票
投票
有多种选择。你可以纠正你的代码,改变类型的 DisplayBook 到valuetle(或创建单独的类型,以便于阅读)。
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)与填充用户关系。
P.S.
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();
1
投票
投票
不需要分别查询每个表,然后连接。 让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模型中使用属性来定义这些关系。
例子:你可以在你的EF模型中使用属性来定义这些关系。
[ForeignKey("BookId")]
public virtual TblBook Book { get; set; }
EDIT:分解你需要返回的内容。
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
});