这是ASP .net EF核心。
我有2节课。提名与用户具有一对多的关系。
提名将具有指向用户ID的外键。
课程:
public class Nomination
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int NominationId { get; set; }
public int NomineeUserId { get; set; }
public int NominationYear { get; set; }
public User Nominee { get; set; }
}
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailId { get; set; }
public byte[] PasswordHash { get; set; }
public byte[] PasswordSalt { get; set; }
}
public class UserDto
{
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
上下文:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasKey(x => x.UserId);
modelBuilder.Entity<User>().Property(x => x.UserId).ValueGeneratedOnAdd();
modelBuilder.Entity<Nomination>().HasKey(x => x.NominationId);
modelBuilder.Entity<Nomination>().Property(x => x.NominationId).ValueGeneratedOnAdd();
modelBuilder.Entity<Nomination>().HasOne(x => x.Nominee).WithMany().HasForeignKey(x => x.NomineeUserId).OnDelete(DeleteBehavior.Restrict);
}
控制器GETALL:
public async Task<ActionResult<IEnumerable<Nomination>>> GetNomination()
{
return await _context.Nomination
.Include(n => n.NominationDetails)
.Include(n => n.Nominee)
.ToListAsync();
}
当我执行GETALL for Namination时,我会收到“ Nominee”(用户)的完整对象,包括密码。 我需要UserDTO而不是User。我不需要用户的其他属性
我应该如何更改代码以实现此目的?
答案 0 :(得分:2)
如果您不使用诸如AutoMapper之类的映射库,则可以使用LINQ选择并返回如下新类型:
假设我们也创建了一个NominationDto
:
NominationDto.cs
public class NominationDto
{
public int NominationId { get; set; }
public int NomineeUserId { get; set; }
public int NominationYear { get; set; }
public UserDto Nominee { get; set; }
}
var nominations = _context.Nomination
.Include(n => n.NominationDetails)
.Include(n => n.Nominee)
.Select(nomination => new NominationDto
{
NominationId = nomination.NominationId,
NomineeUserId = nomination.NomineeUserId,
NominationYear = nomination.NominationYear,
Nominee = new UserDto
{
UserId = nomination.Nominee.UserId,
FirstName = nomination.Nominee.FirstName,
LastName = nomination.Nominee.LastName
}
}).ToListAsync();
但是,如果可能的话,我建议使用AutoMapper
或其他映射库。它将处理将Nomination
和User
实体对象映射到NominationDto
和UserDto
对象。然后,您无需手动进行操作。
(我尚未测试上面的代码,但是我认为应该可以将您放在一个不错的位置。)
编辑 在对原始答案发表评论后,我更新了上面代码的LINQ部分。
答案 1 :(得分:2)
在.Select()
之前使用LINQ的.ToListAsync()
函数编写一个选择投影。
这将创建一个SQL查询以仅获取您在LINQ中选择的那些DB列。
例如提名Dto
public class NominationDto
{
public int NominationId { get; set; }
public int NomineeUserId { get; set; }
public int NominationYear { get; set; }
public UserDto Nominee { get; set; }
}
您的查询可能是:
var nominations = await _context.Nomination
.Include(n => n.NominationDetails)
.Include(n => n.Nominee)
.Select(nomination => new NominationDto
{
NominationId = nomination.NominationId,
NomineeUserId = nomination.NomineeUserId,
NominationYear = nomination.NominationYear,
Nominee = new UserDto
{
UserId = nomination.Nominee.UserId,
FirstName = nomination.Nominee.FirstName,
LastName = nomination.Nominee.LastName
}
}).ToListAsync();
请注意,您可能不需要.Include(n => n.NominationDetails)
,因为在此查询中,没有从NominationDetails中获取/选择/投影任何内容。
此外,如果您不打算跟踪这些实体的变化,则可以在.Select()
之后和.ToListAsync()
之前使用.AsNoTracking()
的方法来告诉EF,您将获得更好的性能,以获得更好的性能跟踪EF对象图中检索到的数据的变化。
您可以在此处找到有关查询跟踪的更多信息:https://docs.microsoft.com/en-us/ef/core/querying/tracking