如何在linq中检索相关对象的属性,select投影

How to retrieve the attribute of related object in linq, select projection

我正在尝试在我的 viewmodel 中检索 Person 名称,同时在以下代码中进行投影:

// GET api/Tickets
    public IQueryable Get()
    {
        var model = Uow.Tickets.GetAll().OrderByDescending(m => m.DateTimeTag)
            .Select(m => new TicketViewModel
             {
                 Id = m.Id,
                 TicketTitle = m.TicketTitle,
                 TicketBody = m.TicketBody,
                 DateTimeTag = m.DateTimeTag,
                 //AssignedTo = Uow.Persons.GetById(m.AssignedToPersonId).Name,
                 Status = m.Status.ToString(),
                 NoOfReplys = m.Replys.Count()
             });
        return model;
    }

但是当我取消注释 AssignedTo 行时,它给出了错误:

InnerException: { Message: "An error has occurred.", ExceptionMessage: "LINQ to Entities does not recognize the method 'Ticketing.Model.Person GetById(Int32)' method, and this method cannot be translated into a store expression.", ExceptionType: "System.NotSupportedException", StackTrace: " at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) blah blah blah

TicketViewModel class 是:

public class TicketViewModel
{
    public int Id { get; set; }
    public string TicketTitle { get; set; }
    public string TicketBody { get; set; }
    public DateTime DateTimeTag { get; set; }       
    public string AssignedTo { get; set; }
    public string Status { get; set; }
    public int NoOfReplys { get; set; }
}

实际Ticketclass是:

public class Ticket
{
    public int Id { get; set; }
    public string TicketTitle { get; set; }
    public string TicketBody { get; set; }
    public DateTime DateTimeTag { get; set; }
    public int AssignedToPersonId { get; set; }
    public Status Status { get; set; }
    public virtual ICollection<Reply> Replys { get; set; }

}

我想要的输出是:

[
 {
  Id: 3,
  TicketTitle: "a problem",
  TicketBody: "problem descripted here.",
  DateTimeTag: "2012-04-21T00:00:00",
  AssignedTo: "Peter", <== ATTENTION!!!
  Status: "Open",
  NoOfReplys: 0
 }
]

这里,Peter是工单对象中id所在的人的名字。 我的目标是显示名称而不是 personId。 可能有更好的方法,请帮助我做到这一点。 谢谢

在这种情况下,我认为您的 属性:

public int AssignedToPersonId { get; set; }

应该是:

public Person AssignedToPerson { get; set; }

在您的工单中 class。映射到引用通常更好,这样您就可以使用 Linq 访问这样的属性。这样给你带来麻烦的线路可以是:

AssignedTo = AssignedToPerson.Name

它现在无法正常工作的原因是 Entity Framework 不知道如何转换您的线路:

Uow.Persons.GetById(m.AssignedToPersonId).Name

到查询表达式。通过使用上面提到的引用,您将在两个表之间创建一个连接,并在单个查询中取回所需的数据。

另一个可能不太吸引人的选择是将 Id 存储在视图模型中,然后在 Linq 查询之外查询名称。这将起作用,因为您已经从数据库中检索了项目。以下未经测试的示例:

public IQueryable Get()
{
    var model = Uow.Tickets.GetAll().OrderByDescending(m => m.DateTimeTag)
            .Select(m => new TicketViewModel
             {
                 Id = m.Id,
                 TicketTitle = m.TicketTitle,
                 TicketBody = m.TicketBody,
                 DateTimeTag = m.DateTimeTag,
                 AssignedToPersonId = m.AssignedToPersonId,
                 Status = m.Status.ToString(),
                 NoOfReplys = m.Replys.Count()
             }).ToList();
    model.ForEach(m => m.AssignedTo = Uow.Persons.GetById(m.AssignedToPersonId).Name);
    return model;
}

但是请注意,第二种方法是针对第一个查询中返回的每个 Ticket 对象对数据库进行额外查询。