如何在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; }
}
实际Ticket
class是:
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 对象对数据库进行额外查询。
我正在尝试在我的 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; }
}
实际Ticket
class是:
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 对象对数据库进行额外查询。