Я пытаюсь использовать функцию Multimapping в dapper, чтобы вернуть список ProductItems и связанных клиентов.
[Table("Product")]
public class ProductItem
{
public decimal ProductID { get; set; }
public string ProductName { get; set; }
public string AccountOpened { get; set; }
public Customer Customer { get; set; }
}
public class Customer
{
public decimal CustomerId { get; set; }
public string CustomerName { get; set; }
}
Мой код dapper выглядит следующим образом
var sql = @"select * from Product p
inner join Customer c on p.CustomerId = c.CustomerId
order by p.ProductName";
var data = con.Query<ProductItem, Customer, ProductItem>(
sql,
(productItem, customer) => {
productItem.Customer = customer;
return productItem;
},
splitOn: "CustomerId,CustomerName"
);
Это работает нормально, но мне кажется, что мне нужно добавить полный список столбцов в параметр splitOn, чтобы вернуть все свойства клиентов. Если я не добавлю «CustomerName», он вернет null. Не понимаю ли я основную функциональность функции множественного сопоставления. Я не хочу каждый раз добавлять полный список имен столбцов.
Ответы:
Я только что провел тест, который отлично работает:
В качестве точки разделения необходимо указать параметр splitOn, по умолчанию он равен Id. Если есть несколько точек разделения, вам нужно будет добавить их в список, разделенный запятыми.
Допустим, ваш набор записей выглядит так:
Dapper необходимо знать, как разбить столбцы в этом порядке на 2 объекта. Беглый взгляд показывает, что
CustomerId
, следовательно, Заказчик начинает с столбцаsplitOn: CustomerId
.Здесь есть большое предостережение, если порядок столбцов в базовой таблице по какой-то причине перевернут:
splitOn: CustomerId
приведет к нулевому имени клиента.Если вы укажете
CustomerId,CustomerName
точки разделения, dapper предполагает, что вы пытаетесь разделить набор результатов на 3 объекта. Первый начинается с начала, второй начинается сCustomerId
, третий - сCustomerName
.источник
spliton
, то естьCustomerId,CustomerName
неCustomerId, CustomerName
, так как Щеголеватый неTrim
результаты строки раскола. Он просто выдаст общую ошибку spliton. Однажды свела меня с ума.Наши таблицы названы так же, как и ваша, где что-то вроде «CustomerID» может быть возвращено дважды с помощью операции «select *». Следовательно, Dapper выполняет свою работу, но просто разделяет слишком рано (возможно), потому что столбцы будут:
Это делает параметр spliton: не таким полезным, особенно когда вы не уверены, в каком порядке возвращаются столбцы. Конечно, вы можете вручную указать столбцы ... но сейчас 2017 год, и мы просто редко делаем это для получения базовых объектов.
Что мы делаем, и он отлично работал для тысяч запросов в течение многих лет, - это просто использовать псевдоним для Id и никогда не указывать spliton (с использованием идентификатора Dapper по умолчанию).
... вуаля! По умолчанию Dapper будет разделяться только по идентификатору, и этот идентификатор встречается перед всеми столбцами «Клиент». Конечно, он добавит дополнительный столбец к вашему набору результатов возврата, но это чрезвычайно минимальные накладные расходы для добавленной утилиты, которая точно знает, какие столбцы принадлежат какому объекту. И вы можете легко это расширить. Нужна информация об адресе и стране?
Лучше всего то, что вы четко показываете в минимальном количестве sql, какие столбцы связаны с каким объектом. Остальное сделает Dapper.
источник
Предполагая следующую структуру, где '|' - точка разделения, а Ts - объекты, к которым следует применить отображение.
Ниже приведен запрос dapper, который вам нужно будет написать.
Итак, мы хотим, чтобы TFirst отображал col_1 col_2 col_3, для TSecond col_n col_m ...
Выражение splitOn переводится как:
Начните отображение всех столбцов в TFrist, пока не найдете столбец с именем или псевдонимом «col_3», а также включите «col_3» в результат сопоставления.
Затем начните отображение в TSecond всех столбцов, начиная с col_n, и продолжайте отображение до тех пор, пока не будет найден новый разделитель, которым в данном случае является col_A, который отмечает начало отображения TThird и так далее.
Столбцы запроса sql и свойства объекта сопоставления находятся в отношении 1: 1 (это означает, что они должны называться одинаково), если имена столбцов, полученные в результате запроса sql, отличаются, вы можете присвоить им псевдоним, используя 'AS [ Some_Alias_Name] 'выражение.
источник
Есть еще один нюанс. Если поле CustomerId имеет значение null (обычно в запросах с левым соединением) Dapper создает ProductItem с Customer = null. В приведенном выше примере:
И даже еще один нюанс / ловушка. Если вы не сопоставляете поле, указанное в splitOn, и это поле содержит значение null, Dapper создает и заполняет связанный объект (в данном случае Customer). Чтобы продемонстрировать использование этого класса с предыдущим sql:
источник
Я делаю это в основном в своем репо, хорошо работает для моего варианта использования. Думал поделюсь. Может, кто-то продлит это дальше.
Некоторые недостатки:
Код:
источник
Если вам нужно отобразить большой объект, напишите, что каждое поле должно быть сложной задачей.
Я попробовал ответить @BlackjacketMack, но в одной из моих таблиц есть столбец Id, других нет (я знаю, что это проблема с дизайном БД, но ...), тогда эта вставка дополнительного разделения на dapper, поэтому
У меня не работает. Потом я закончил с небольшим изменением к этому, просто вставить точку разделения с именем , которое не совпадает с любым полем на столах, в случае может изменена
as Id
путемas _SplitPoint_
, окончательный внешний вид SQL скрипт , как это:Затем в dapper добавьте только один splitOn как этот
источник