Создает ли Dapper новый объект для повторяющихся результатов соединения?

Когда Dapper выполняет JOIN, вызывает ли он конструктор для каждого a, b, c? или каждый уникальный a,b, c?

string sql = @"SELECT a.*, b.*, c.* 
               FROM A a
               JOIN B b ON b.Id = a.BId
               JOIN C c ON b.Id = c.BId";

var results = db.Query<A, B, C, A>(sql, (a, b, c) => { return a; });

Например, если у меня есть дубликаты c, будет ли Dapper вызывать конструктор c много раз?

Или он заметит, что идентификаторы одинаковы между строками, и передаст мне один и тот же объект для всех экземпляров, где идентификатор одинаков?

Изменить:

После некоторого тестирования похоже, что он вызывает конструктор несколько раз для повторяющихся значений.

Есть ли простой способ обойти это с помощью Dapper API?


person Charles W    schedule 09.01.2015    source источник
comment
Просто добавьте DISTINCT в свой запрос   -  person Panagiotis Kanavos    schedule 09.01.2015
comment
Я перефразировал вопрос. Для ясности я ищу не отдельные строки, а отдельные части строки, которые Dapper возвращает с помощью своего метода Query<TFirst, TSecond, ..., TReturn>().   -  person Charles W    schedule 09.01.2015


Ответы (1)


Я собираюсь предложить свое решение, но оставлю этот вопрос открытым на случай, если у кого-то появится идея получше.

Вот что я сделал:

List<dynamic> results = db.Query<dynamic, dynamic, dynamic, dynamic>(sql,
    (a, b, c) => { return new { a, b, c }; }).ToList(); // splitOn: 'Id'

List<dynamic> a_ids = new List<dynamic>();
List<dynamic> b_ids = new List<dynamic>();
List<dynamic> c_ids = new List<dynamic>();

List<A> unique_as = new List<A>();
List<B> unique_bs = new List<B>();
List<C> unique_cs = new List<C>();
foreach (var row in results)
{
    var a = row.a;
    var b = row.b;
    var c = row.c;
    if(!a_ids.Contains(a.Id)) unique_as.Add(new A(a.Id));
    if(!b_ids.Contains(b.Id)) unique_bs.Add(new B(b.Id));
    if(!c_ids.Contains(c.Id)) unique_cs.Add(new C(c.Id));
}

Было бы неплохо, если бы Dapper как-то поддержал это в будущем, но до тех пор я надеюсь, что это поможет кому-то еще.

person Charles W    schedule 09.01.2015
comment
Почему должен Dapper удалять повторяющиеся строки, если вы не указываете ключевое слово DISTINCT в своем запросе? Это противоречит тому, что все ожидают при выполнении оператора SQL. - person Panagiotis Kanavos; 09.01.2015
comment
@PanagiotisKanavos Поскольку строка отличается, но, возможно, часть строки (a, b или c) не отличается. results[0].a.Id == results[1].a.Id не означает results[0].c.Id == results[1].c.Id - person Charles W; 09.01.2015
comment
Тогда оператор SQL неверен. Он должен указывать только те столбцы, которые действительно необходимы. Использование * без причины является источником множества ошибок и плохой производительности в SQL. Мало того, что он извлекает гораздо больше данных, это может привести к неэффективному запросу, потому что сервер должен проверять больше индексов или обращаться непосредственно к таблице, когда он может найти необходимые данные в индексе. - person Panagiotis Kanavos; 09.01.2015