Dapper 및 다중 매핑을 사용하여 특정 순서로 일대 다 레코드를 반환하려면 어떻게해야합니까?

dapper multi-mapping

문제

Github에서 :

Dapper를 사용하면 단일 행을 여러 객체에 매핑 할 수 있습니다. 불필요한 쿼리 및 열렬한로드 연결을 방지하려면이 기능이 중요합니다.

예:

포스트와 사용자의 두 클래스를 고려하십시오.

> class Post {
>     public int Id { get; set; }
>     public string Title { get; set; }
>     public string Content { get; set; }
>     public User Owner { get; set; } }
> 
> class User {
>     public int Id { get; set; }
>     public string Name { get; set; } } 

이제 posts와 users 테이블을 조인하는 쿼리를 매핑하려고한다고 가정 해 보겠습니다. 지금까지 2 개의 쿼리 결과를 결합해야하는 경우이를 표현하기 위해 새로운 객체가 필요하지만이 경우에는 User 객체를 Post 객체 내에 배치하는 것이 더 적합합니다.

이 작업을 수행 할 때 (수업은 이름이 다르지만 구조가 같음) 게시물과 사용자, 게시물 및 사용자가 표시됩니다. 나는 웹 API를 사용하고 있기 때문에 모든 JSON이 중요하다. 이것은 Management Studio에서 SQL을 연속적으로 수행하면 볼 수있는 방법입니다. 많은 행과 해당 User 레코드를 얻습니다.

한 사용자와 모든 게시물을 배열에 포함하고 다음 사용자, 게시물 배열 등을 가진 JSON을 다시 보내려는 경우 어떻게해야합니까?

id   title    content   id    name
1    Article1 Content1  55  Smith
2    Article2 Content2  55  Smith
3    Article3 Content3  55  Smith

JSON은 사용자 정보를 계속 가지고 있습니다 (예상했지만 원하지 않음). 거꾸로.

내가 원한 것은 JSON 객체이다. (이게 옳은 것 같다.)

{
  "User": 55,
  "Name": "Smith",
  "Post": [
    {
      "id": 1,
      "title": "title1",
      "content":"MyContent1"
    },
    {
      "id": 2,
      "title": "title2",
      "content":"MyContent2"
    },
    {
      "id": 3,
      "title": "title3",
      "content":"MyContent2"
    }
  ]
}

어떻게해야합니까? 지금 나는 반대를 얻는다. 나는 주변의 수업을 간단히 바꿀 줄 알았지 만 기스 instructions에 대한 설명 때문에 "더 이해가된다"는 부분이 아닙니다. 나는 이것을 사용하고있다.

(List<Post>)db.Query<Post, User, Paper>(sqlString, (post, user) => { post.user = user; return post; }, splitOn: "id");

나는 여기에 splitOn이 필요 없다는 것을 알고 있지만, 나의 실제 질의에서 이름은 id와 다르다.

이것은 아주 가깝습니다 :

https://www.tritac.com/developers-blog/dapper-net-by-example/

public class Shop {
  public int? Id {get;set;}
  public string Name {get;set;}
  public string Url {get;set;}
  public IList<Account> Accounts {get;set;}
}

public class Account {
  public int? Id {get;set;}
  public string Name {get;set;}
  public string Address {get;set;}
  public string Country {get;set;}
  public int ShopId {get;set;}
}

var lookup = new Dictionary<int, Shop>()
conn.Query<Shop, Account, Shop>(@"
                    SELECT s.*, a.*
                    FROM Shop s
                    INNER JOIN Account a ON s.ShopId = a.ShopId                    
                    ", (s, a) => {
                         Shop shop;
                         if (!lookup.TryGetValue(s.Id, out shop)) {
                             lookup.Add(s.Id, shop = s);
                         }
                         if (shop.Accounts == null) 
                             shop.Accounts = new List<Account>();
                         shop.Accounts.Add(a);
                         return shop;
                     },
                     ).AsQueryable();

var resultList = lookup.Values;

첫 번째 객체 식별자를 만듭니다. 내가 그걸 좋아할 지 모르겠다. 그러나 이것은 내가 묻는 것처럼 책의 배열을하고, 나는 특별한 물건을 만들 필요가 없었습니다. 원래 Google 코드에 있어야했는데 Github에서이 테스트를 찾을 수 없었습니다.

인기 답변

또 다른 옵션은 사용하는 것입니다. QueryMultiple

    [Test]
    public void TestQueryMultiple()
    {
        const string sql = @"select UserId = 55, Name = 'John Doe'
                    select PostId = 1, Content = 'hello' 
                    union all select PostId = 2, Content = 'world'";

        var multi = _sqlConnection.QueryMultiple(sql);
        var user = multi.Read<User>().Single();
        user.Posts = multi.Read<Post>().ToList();

        Assert.That(user.Posts.Count, Is.EqualTo(2));
        Assert.That(user.Posts.First().Content, Is.EqualTo("hello"));
        Assert.That(user.Posts.Last().Content, Is.EqualTo("world"));
    }

최신 정보:

여러 사용자와 게시물을 반환하려면 다음 단계를 따르세요.

    [Test]
    public void TestQueryMultiple2()
    {
        const string sql = @"select UserId = 55, Name = 'John Doe'
                    select UserId = 55, PostId = 1, Content = 'hello' 
                    union all select UserId = 55, PostId = 2, Content = 'world'";

        var multi = _sqlConnection.QueryMultiple(sql);
        var users = multi.Read<User>().ToList();
        var posts = multi.Read<Post>().ToList();

        foreach (var user in users)
        {
            user.Posts.AddRange(posts.Where(x => x.UserId == user.UserId));
        }

        Assert.That(users.Count, Is.EqualTo(1));
        Assert.That(users.First().Posts.First().Content, Is.EqualTo("hello"));
        Assert.That(users.First().Posts.Last().Content, Is.EqualTo("world"));
    }


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow