仅包含一个属性,而不是整个数据库行

时间:2016-10-22 12:43:57

标签: c# asp.net entity-framework asp.net-core entity-framework-core

型号:

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()

你会如何解决这个问题?

4 个答案:

答案 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()获取所有相关实体,然后循环它们并省略我不想返回的属性值。如果您的模型发生变化,则需要进行一些维护,但令人惊讶的是,它并没有显着影响响应时间。