API-интерфейсы Dapper — multi-mapping гарантируют, что вы установите разделение

#.net #asp.net-mvc #dapper

#.net #asp.net-mvc #dapper

Вопрос:

Для кода, показанного ниже, я получаю следующее сообщение об ошибке.

*** Ошибка ***

При использовании API с несколькими отображениями убедитесь, что вы установили параметр splitOn, если у вас есть ключи, отличные от Id (параметр ‘splitOn’)

Насколько я понимаю, я передаю параметр splitOn, я упускаю что-то очевидное?

Код

 
 using (var connection = new Microsoft.Data.SqlClient.SqlConnection(connectionString))
                {
                    connection.Open();
                    LookupTables = connection.Query<LookupTable, List<LookupValue>, LookupTable>("exec [lookups].[SelAllLookupTable]", 
                        (lookuptable, lookupvalue) => {
                            lookuptable.LookUpValues = lookupvalue.ToList<LookupValue>(); 
                            return lookuptable;
                        }, splitOn: "LookupValueID").ToList();
                }


  

Обновить

Сохраненный код процедуры

 
ALTER PROCEDURE [lookups].[SelAllLookupTable]
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    SELECT lt.[LookupTableID],
        lt.[GUID],
        lt.[CreatedBy],
        lt.[CreatedOn],
        lt.[UpdatedBy],
        lt.[UpdatedOn],
        lt.[ChangeReason],
        lt.[Name],
        lt.[Description],
        lv.[LookupValueID],
        lv.[LookupTableID],
        lv.[GUID],
        lv.[CreatedBy],
        lv.[CreatedOn],
        lv.[UpdatedBy],
        lv.[UpdatedOn],
        lv.[ChangeReason],
        lv.[Description],
        lv.[DisplayOrderNo]
    FROM lookups.LookupTable lt
    LEFT JOIN lookups.LookupValue lv ON lt.LookupTableID = lv.LookupTableID
END


  

Комментарии:

1. Не могли бы вы добавить SQL-код хранимой процедуры?

2. @Steve Я добавил сохраненный код процедуры в спасибо

3. Я бы попытался добавить имена полей вместо *, и вам нужен только идентификатор для объединенной таблицы в параметре splitOn LookupTableID

4. Спасибо, что немного изменили код, и теперь я получаю результаты, хотя я ожидал 1 таблицу поиска со списком, содержащим 2 поисковых значения, но у меня есть 2 таблицы поиска без значений

Ответ №1:

У меня нет ваших данных, но я думаю, вам следует изменить свой код таким образом

 // Where we store the distinct LookUpTable found by the query
Dictionary<int, LookUpTable> result = new Dictionary<int, LookUpTable>();

using (var connection = new Microsoft.Data.SqlClient.SqlConnection(connectionString))
{
    connection.Open();
    var LookupTables = connection.Query<LookupTable, LookUpValue, LookupTable>("exec [lookups].[SelAllLookupTable]",
        (lkt, lkv) =>
        {
            // Check if we have the instance already in the dictionary
            // add it if not, 
            if (!result.ContainsKey(lkt.LookUpTableID))
               result.Add(lkt.LookUpTableID, lkt);
            result[lkt.LookupTableID].LookUpValues.Add(lkv);
            return lkt;
        }, splitOn: "LookupValueID").ToList();
}
return result.Values.ToList();
  

Dapper не будет создавать и передавать список LookupValue напрямую, но он будет перебирать записи, создавая объекты из каждой возвращенной записи и передавая эти объекты один за другим в лямбда-выражение.
Ваше лямбда-выражение может использовать словарь для хранения каждого полученного объекта LookupTable и добавления объекта LookupValue в его свойство. Когда Dapper завершает итерацию записи, ваши объекты сохраняются в коллекции значений словаря

Конечно, это предполагает, что таблица поиска вашего класса имеет List<LookUpValue> свойство

 public class LookupTable
{
    public int LookupValueID { get; set; }
    .... other properties ....
    public List<LookUpValue> LookUpValues {get;set} = new List<LookUpValue>();
}
  

Обратите внимание, как свойство создает список при инициализации, чтобы избежать сложной логики в лямбда-выражении Dapper.

Комментарии:

1. Код запущен сейчас и возвращает данные, однако в результате я ожидал получить одну таблицу поиска со списком, содержащим 2 поисковых значения, однако я получаю 2 таблицы поиска с 1 поисковым значением в каждой

2. Я вижу, теперь я лучше понял ваш случай и изменил пример. Это обычный сценарий с dapper, который может быть разрешен с помощью переменной словаря

3. Ах, большое спасибо, вы лучшие! это работает так, как я хотел 🙂

4. Перепроверил этот код и обнаружил ошибку. В словаре следует добавить ссылку на таблицу поиска, а не на поисковое значение (Intellisense недостаточно ценится, пока вы не напишете подобный код вручную)