Как сделать запрос из объекта со списком объектов в Dapper C # - PullRequest
0 голосов
/ 14 марта 2019

Предположим, у меня есть следующие таблицы:

tb_1: |user_id|user_name|email|age|

tb_2: |item_id|item_name|value|

tb_3: |user_id|item_id|

И у меня есть модели ниже:

Элемент:

public class Item {
    public string Name {get; set;}
    public int Value {get; set;}
}

Пользователь:

public class User {
    public Guid UserId {get; set;}
    public List<Item> Itens {get; set;}
}

Я использую следующий запрос для выполнения поиска:

using(var connection = ...)
{
    var query1 = "SELECT ... FROM tb_1";
    var query2 = "SELECT ... FROM tb_2 JOIN tb_3 ON ... WHERE tb_3.user_id = @UserId";
    var users = await connection.QueryAsync<User>(query1);
    foreach(var user in users)
    {
        user.Itens = await connection.QueryAsync<Item>(query2, user.UserId);
    }
    return users;
}

Можно ли удалить foreach и использовать только один запрос?

PS: Таблицы от N доN.

Ответы [ 2 ]

0 голосов
/ 15 марта 2019

Я смог решить проблему.Я исследовал и нашел решение в документации Dapper из запроса «один ко многим».

string sql = "SELECT TOP 10 * FROM Orders AS A INNER JOIN OrderDetails AS B ON A.OrderID = B.OrderID;";

using (var connection = new SqlCeConnection("Data Source=SqlCe_W3Schools.sdf"))
{           
    var orderDictionary = new Dictionary<int, Order>();


    var list = connection.Query<Order, OrderDetail, Order>(
    sql,
    (order, orderDetail) =>
    {
        Order orderEntry;

        if (!orderDictionary.TryGetValue(order.OrderID, out orderEntry))
        {
        orderEntry = order;
        orderEntry.OrderDetails = new List<OrderDetail>();
        orderDictionary.Add(orderEntry.OrderID, orderEntry);
        }

        orderEntry.OrderDetails.Add(orderDetail);
        return orderEntry;
    },
    splitOn: "OrderID")
    .Distinct()
    .ToList();

    Console.WriteLine(list.Count);

    FiddleHelper.WriteTable(list);
    FiddleHelper.WriteTable(list.First().OrderDetails);
}

Ссылка: Запрос Multi-Mapping (один ко многим)

0 голосов
/ 14 марта 2019

Я бы сказал «да, но: переписать запрос, чтобы использовать соединение», т.е.

var query = @"
SELECT ... FROM tb_1

SELECT ... FROM tb_2 JOIN tb_3 ON ... 
INNER JOIN (SELECT UserId FROM tb_1) x -- your original query here
    on tb_3.user_id = x.UserId   -- but as a sub-query
";

, затем используйте QueryMultiple. Это возвращает две сетки , поэтому вам нужно прочитать дважды - затем сгруппировать и разделить на сайте вызова.

using (var multi = connection.QueryMultiple(sql, ...))
{
    var users = multi.Read<User>().AsList();
    var allItems = multi.Read<Item>().AsList();

    var usersById = users.ToDictionary(x => x.Id);
    foreach(var item in allItems) {
        usersById[item.UserId].Items.Add(item);
    }
    return users;
}
...