如何在不迭代的情况下将Linq结果转换为DTO类对象

时间:2013-02-27 23:55:49

标签: c# .net linq entity-framework

我正在构建一个Web API项目,该项目将提供给第三方并由我自己的Web应用程序使用。 Web API方法将返回复杂类型/对象的JSON表示。这些是我可以提供给第三方的预定义类,因此他们了解数据的结构,并可以反序列化JSON。我会将这些类称为DTO类,直到有人纠正我为止。

我有以下自动生成的实体模型(来自数据库),这是User类,无论如何都与Scan表有关系(为了这个问题可以忽略关系)......

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从数据库中获取用户,然后解析结果并返回List&lt;&gt; 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查询中做这种事情(例如这个问题中的答案Mapping Linq Query results to a DTO class)。

我不确定应该在何处/如何实现IEnumerable以在我的对象上启用此类型的Linq查询,并且我也不确定如何编写类似于上面引用的问题中的查询但是对于我的更简单的方案。

提前感谢您的帮助。

P.S。请忽略我通过Web API公开用户名和密码的事实,以及我一次性返回所有用户的事实。以上是我的代码的简化版本,用于此问题。

4 个答案:

答案 0 :(得分:35)

完整的方法可以是:

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()方法时确实会发生这种情况。

答案 1 :(得分:9)

您可以使用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();
}

答案 2 :(得分:3)

如果我们使用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();
    }
}

答案 3 :(得分:-1)

在我的查询中,我有多个子节点的父表。

clearfix:after,
clearfix:before {
  content: " ";
  /* Older browser do not support empty content */
  visibility: hidden;
  display: block;
  height: 0;
  clear: both;
}

当我在linq查询中使用 if($initials) { $left_letter = strtolower(substr($initials, 0, 1)); $center_letter = strtoupper(substr($initials, 1, 1)); $right_letter = $this->substitute_circle_monog_third_char(substr($initials, 2, 1)); $val = $left_letter . $center_letter . $right_letter; } else { $val = 'rE4'; } $html = '<canvas id="canvas" width="130" height="130"></canvas>'; $html .= '<script type="text/javascript">'; $html .= 'jQuery(window).load(function(){'; $html .= 'var canvas = new fabric.Canvas("canvas");'; $html .= 'var text = new fabric.Text("' . $val . '", {'; $html .= 'fontFamily : "circle-monogram",'; // $html .= 'fontSize : 100,'; // $html .= 'selectable : false,'; // $html .= 'top : 3,'; // $html .= 'left : 3'; $html .= '});'; $html .= 'canvas.add(text);'; $html .= '})'; $html .= '</script>'; // output the html return $html; } 时,它会给出错误。 现在我在linq查询中使用匿名类型并将其转换为下一个查询,如此

public class TeamWithMembers
        {
            public int TeamId { get; set; }
            public string TeamName { get; set; }
            public string TeamDescription { get; set; }
            public List<TeamMembers> TeamMembers { get; set; }
        }

其中ToList()是linq查询的结果集。