型号:
public class Word
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime? WhenCreated { get; set; }
public ApplicationUser Author { get; set; }
[NotMapped]
public string AuthorName
{
get
{
if (Author != null)
{
return Author.UserName;
}
else {
return "";
}
}
}
public List<Definition> Definitions { get; set; }
}
控制器:
[HttpGet]
public IEnumerable<Word> Get()
{
return _db.Words.Include(x=>x.Author).ToList();
}
我的控制器现在返回整个ApplicationUser
类,它是Word
的属性之一。我只想发送ApplicationUser
UserName
的一个属性。我怎么能这样做?
我添加了AuthorName
,它只返回我想要的数据ApplicationUser
。不幸的是,我仍然需要.Include(x=>x.Author)
来使这个属性工作。我可以在数据序列化过程中忽略包括Author
(在向用户发送数据时隐藏它)吗?
我知道我可以使用.Select()
方法,但它需要我输入我需要的所有属性。如果我将来修改我的模型,我将需要更新所有那些不方便且浪费时间的.Select()
。
你会如何解决这个问题?
答案 0 :(得分:4)
您需要创建一个Dto对象并为其分配值并返回Dto。
DTO
public class WordDto
{
public string Title { get; set; }
public DateTime? WhenCreated { get; set; }
public string AuthorName { get; set; }
}
然后在你的行动中
[HttpGet]
public async Task<IEnumerable<WordDto>> Get()
{
return _db.Words
.Include(x=>x.Author)
.Select(x =>
new WordDto
{
Title = x.Title,
DateTime = x.WhenCreated,
AuthorName = x.Author?.UserName ?? string.Empty
}
)
.ToListAsync();
}
答案 1 :(得分:2)
您可以尝试如下所示。
注意:您无需在此处使用Include
。
[HttpGet]
public async Task<IEnumerable<Word>> Get()
{
return _db.Words.Select(x => new
{
Word = x,
AuthorName = x.Author.UserName
}
).ToList();
}
答案 2 :(得分:1)
创建一个View模型并使用AutoMapper进行填充。请查看使用AutoMapper和ProjectTo扩展程序https://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions
这样,如果您向View模型添加属性,如果它们存在于您的EF模型中,它们将自动映射
因此,创建一个具有适当命名的必需属性的VM(请参阅命名约定的AutoMapper文档):
public class WordVM
{
public string Title { get; set; }
public DateTime? WhenCreated { get; set; }
public string AuthorName { get; set; }
}
然后使用AutoMapper进行投影(它将执行任何必需的包含,因此如果您稍后更改了VM,那么它将处理它)
_db.Words.ProjectTo<WordVM>().ToList();
您不需要NotMapped
属性AutoMapper会将导航属性Author
和作者属性Name
映射到AuthorName
答案 3 :(得分:0)
我的解决方法是使用.include()获取所有相关实体,然后循环它们并省略我不想返回的属性值。如果您的模型发生变化,则需要进行一些维护,但令人惊讶的是,它并没有显着影响响应时间。