Asp.net 如何仅从EF core中的相关数据中获取少量属性?
这是ASP.NETEF核心 我有两门课。具有一对多关系的提名和用户 提名将具有指向用户ID的外键 课程:Asp.net 如何仅从EF core中的相关数据中获取少量属性?,asp.net,.net,entity-framework,.net-core,ef-core-2.2,Asp.net,.net,Entity Framework,.net Core,Ef Core 2.2,这是ASP.NETEF核心 我有两门课。具有一对多关系的提名和用户 提名将具有指向用户ID的外键 课程: public class Nomination { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int NominationId { get; set; } public int NomineeUserId { get; set; } public int Nom
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时,我收到了包括密码内容在内的提名用户的完整对象。
我需要UserDTO而不是User。我不需要用户的其他属性
我应该如何更改代码以实现这一点?如果您没有使用映射库,例如,可以使用LINQ选择并返回如下新类型: 假设我们也创建了一个命名对象: 提名至.cs 公开课提名 { 公共int提名ID{get;set;} 公共用户标识{get;set;} public int namignationyear{get;set;} 指定人{get;set;}的公共用户数据 } var提名=_context.namignment .Includen=>n.negationdetails 被提名人 .selectnamitment=>新提名到 { 提名ID=提名。提名ID, 提名用户ID=提名。提名用户ID, 提名, 被提名人=新用户到 { UserId=namignment.namegate.UserId, FirstName=提名。提名人。FirstName, LastName=提名。提名人。LastName } }.ToListAsync; 但是,如果可能,我建议使用AutoMapper或其他映射库。它将处理将提名和用户实体对象映射到提名到和用户到对象的过程。那你就不需要手工了 我还没有测试上面的代码,但我相信这会让你处于一个好的位置 编辑
在对原始答案进行评论后,我更新了上面代码的LINQ部分。如果您没有使用映射库,例如,可以使用LINQ选择并返回如下新类型: 假设我们也创建了一个命名对象: 提名至.cs 公开课提名 { 公共int提名ID{get;set;} 公共用户标识{get;set;} public int namignationyear{get;set;} 指定人{get;set;}的公共用户数据 } var提名=_context.namignment .Includen=>n.negationdetails 被提名人 .selectnamitment=>新提名到 { 提名ID=提名。提名ID, 提名用户ID=提名。提名用户ID, 提名, 被提名人=新用户到 { UserId=namignment.namegate.UserId, FirstName=提名。提名人。FirstName, LastName=提名。提名人。LastName } }.ToListAsync; 但是,如果可能,我建议使用AutoMapper或其他映射库。它将处理将提名和用户实体对象映射到提名到和用户到对象的过程。那你就不需要手工了 我还没有测试上面的代码,但我相信这会让你处于一个好的位置 编辑
在对原始答案进行评论后,我更新了上面代码的LINQ部分。在.tolistSync之前使用LINQ的.select函数编写一个选择投影 这将创建一个SQL查询,以仅获取您在LINQ中选择的那些DB列 例如,提名
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();
请注意,您可能不需要.Includen=>n.NaminationDetails,因为在此查询中,没有从NaminationDetails获取/选择/投影任何内容
此外,如果您不打算跟踪这些实体的更改,那么为了获得更好的性能,您可以使用after.Select和before.ToListAsync方法。AsNoTracking告诉EF您不打算跟踪EF对象图中检索到的数据的更改
您可以在此处找到有关查询跟踪的更多信息:在.toListSync之前使用LINQ的.select函数编写一个选择投影 这将创建一个SQL查询,以仅获取您在LINQ中选择的那些DB列 例如,提名
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();
请注意,您可能不需要.Includen=>n.NaminationDetails,因为在此查询中,没有从NaminationDetails获取/选择/投影任何内容
此外,如果您不打算跟踪这些实体的更改,那么为了获得更好的性能,您可以使用after.Select和before.ToListAsync方法。AsNoTracking告诉EF您不打算跟踪EF对象图中检索到的数据的更改
您可以在此处找到有关查询跟踪的更多信息:这将导致在使用数据库中的所有相关数据具体化查询后出现内存中的投影。为了将对数据库的影响降至最低,应在.ToListAsync.Oops!之前添加select函数!你说得对!谢谢你。我写这篇文章的时候就考虑过了
t、 但无论出于何种原因,我决定将Select放在ToListSync之后。谢谢您的回答!我会尽快试一试,并记下正确答案。关于汽车制造商。我已经创建了一个映射器文件,可以使用CreateMap。我将如何在Controller中继续这种方法?我应该在使用上下文之前映射它?为这些愚蠢的问题道歉。net的新成员。@AthreyaMRBhatt您将注入和IMapper映射器,并将其分配给本地成员,例如控制器构造函数中的\u映射器,然后在Action方法中键入类似\u mapper.MapsourceObject的内容。请阅读有关如何设置AutoMapper的说明:这将导致在使用数据库中的所有相关数据实现查询后出现内存中的投影。为了将对数据库的影响降至最低,应在.ToListAsync.Oops!之前添加select函数!你说得对!谢谢你。我写出来的时候已经考虑过了,但不管出于什么原因,我决定把Select放在ToListSync之后。谢谢你的回答!我会尽快试一试,并记下正确答案。关于汽车制造商。我已经创建了一个映射器文件,可以使用CreateMap。我将如何在Controller中继续这种方法?我应该在使用上下文之前映射它?为这些愚蠢的问题道歉。net的新成员。@AthreyaMRBhatt您将注入和IMapper映射器,并将其分配给本地成员,例如控制器构造函数中的\u映射器,然后在Action方法中键入类似\u mapper.MapsourceObject的内容。请阅读有关如何设置AutoMapper的说明:谢谢您的回答!我会尽快试一试,并对答案进行投票/打分。谢谢你的回答!我会尽快试一试,并把答案改为正确答案。