web-dev-qa-db-ja.com

Linqの結果を反復せずにDTOクラスオブジェクトに変換するにはどうすればよいですか

サードパーティが利用できるようになり、自分のWebアプリケーションでも使用されるWeb APIプロジェクトを構築しています。 Web APIメソッドは、複雑なタイプ/オブジェクトのJSON表現を返します。これらは事前定義されたクラスであり、サードパーティが利用できるようにして、データの構造を理解し、JSONをデシリアライズできるようにします。誰かが私を修正するまで、これらのクラスをDTOクラスと呼びます。

私は次の自動生成されたエンティティモデル(データベースから)を持っていますが、これはスキャンテーブルとの関係を持つUserクラスです(この質問の目的のために関係は無視できます)...

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ユーザーのList <>を返します。

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クラスにマッピングする ) 。

私はオブジェクトでこのタイプのLinqクエリを有効にするためにIEnumerableをどこで/どのように実装する必要があるのか​​分かりません。また、上記の参照された質問のクエリに似ていますが、はるかに簡単なシナリオのためにクエリを書く方法もわかりません。

助けてくれてありがとう。

追伸Web APIを介してユーザー名とパスワードを公開し、すべてのユーザーを一度に返すという事実を無視してください。上記は、この質問の目的のための私のコードの簡略版です。

20
Dan

完全な方法は次のとおりです。

_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()メソッドを呼び出すと実際に発生します。

36

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();
}
9
Reed Copsey

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
Dustin Kingen