如何将Linq结果转换为DTO类对象而无需迭代
本文关键字:对象 迭代 DTO Linq 结果 转换 | 更新日期: 2023-09-27 18:01:33
我正在构建一个Web API项目,该项目将提供给第三方,也由我自己的Web应用程序使用。Web API方法将返回复杂类型/对象的JSON表示。这些是预定义的类,我可以让第三方使用,这样他们就可以理解数据是如何结构化的,并可以反序列化JSON。我将把这些类称为DTO类,直到有人纠正我。
我有以下自动生成的实体模型(从数据库)好吧,这是用户类无论如何与扫描表的关系(关系可以忽略为这个问题的目的)…
public partial class User
{
public User()
{
this.Scans = new HashSet<Scan>();
}
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public bool Active { get; set; }
public virtual ICollection<Scan> Scans { get; set; }
}
和下面的DTO类,我想返回到表示层作为列表(我不认为我应该使用IEnumerable业务到表示?)。
public class User
{
public int Id;
public string Username;
public string Password;
public bool Active;
}
这个组件的业务层目前如下所示。使用Linq从数据库获取用户,然后解析结果并返回POCO用户列表<>
public List<User> Get()
{
List<User> userList = new List<User>();
using (var db = new MyContext())
{
var query = from u in db.Users
orderby u.FirstName
select u;
foreach (var item in query)
{
User user = new User();
user.Id = item.pkUser;
user.Username = item.Username;
user.Password = item.Password;
user.Active = item.Active;
userList.Add(user);
}
}
return userList;
}
像这样解析结果似乎效率低下,我已经看到你可以在没有迭代的Linq查询中做这种事情(例如,这个问题的答案将Linq查询结果映射到DTO类)。
我不确定我应该在哪里/如何实现IEnumerable以启用我的对象上的这种类型的Linq查询,并且我也不确定如何编写类似于上述参考问题中的查询,但对于我的更简单的场景。
提前感谢您的帮助。
注:请忽略的事实,我是通过Web API暴露用户名和密码,我也返回所有用户一次。以上是我的代码的简化版本,用于解决这个问题。
完整的方法可以是:
public List<User> Get()
{
using (var db = new MyContext())
{
return (from u in db.Users
orderby u.FirstName
select new User()
{
Id = u.pkUser,
Username = u.Username,
Password = u.Password,
Active = u.Active
}).ToList();
}
}
你说你想要"不迭代"的结果。使用LINQ也不能消除迭代。您没有在代码中这样做,但它确实发生在您调用ToList()
方法时。
您可以使用LINQ to Objects来进行转换:
using (var db = new MyContext())
{
var query = from u in db.Users
orderby u.FirstName
select u;
return query.AsEnumerable().Select(item =>
new User
{
Id = item.pkUser,
Username = item.Username,
Password = item.Password,
Active = item.Active
}).ToList();
}
如果我们使用AutoMapper,我们可以变得非常紧凑。
在存储库中引导映射器:
Mapper.CreateMap<AutoGenNamespace.User, DtoNamespace.User>();
那么它就相当简单了(返回IEnumerable也没什么错)。
public IEnumerable<User> Get()
{
using (var db = new MyContext())
{
return (from u in db.Users
orderby u.FirstName
select Mapper.Map(u)).AsEnumerable();
}
}
在我的查询中,我有多个孩子的父表。
public class TeamWithMembers
{
public int TeamId { get; set; }
public string TeamName { get; set; }
public string TeamDescription { get; set; }
public List<TeamMembers> TeamMembers { get; set; }
}
当我在linq查询中使用ToList()
时,它给出了错误。现在我在linq查询中使用匿名类型,并将其转换为下一个查询,如
List<TeamModel.TeamWithMembers> teamMemberList = teamMemberQueryResult.AsEnumerable().Select(item =>
new TeamModel.TeamWithMembers() {
TeamId=item.TeamId,
TeamName=item.TeamName,
TeamMembers=item.TeamMembers.ToList()
}).ToList();
其中teamMemberQueryResult
为linq查询的结果集