Dapper параметризованные запросы с автоматически сгенерированными типами LINQ - PullRequest
6 голосов
/ 29 июня 2011

В своей работе я использую комбинацию LINQ и Dapper. Я заменяю свой код LINQ на Dapper местами из соображений производительности. У меня есть много объектов данных LINQ, созданных путем перетаскивания в диаграмму базы данных Visual Studio из SQL Server.

В следующем примере у меня уже есть объект LINQ в памяти, и я хотел бы передать его Dapper в качестве параметров для запроса. Например:

Animal animal = con.Query<Animal>(" select * " +
        " from animal " +
        " where animalid = @AnimalId " +
        " and animaltype = @AnimalType ",
        cagedAnimal).SingleOrDefault();

cagedAnimal содержит открытые свойства AnimalId и AnimalType с геттерами и сеттерами.

Однако при выполнении этого кода я получаю следующую ошибку:

Тип: SMDApp.Models.Animal is не поддерживается dapper

Следующий код работает:

Animal animal = con.Query<Animal>(" select * " +
            " from animal " +
            " where animalid = @AnimalId " +
            " and animaltype = @AnimalType ",
            new 
            { 
            AnimalId = cagedAnimal.AnimalId, 
            AnimalType = cagedAnimal.AnimalType 
            }
            ).SingleOrDefault();

Мне было бы удобнее использовать существующий объект, особенно когда я использую более одного свойства объекта в качестве параметра для запроса. Кто-нибудь может сказать, почему это работает для анонимного объекта, но не для автоматически сгенерированного объекта LINQ?

Отредактировано в ответ на ответ Бена Робинсона.

Отредактировано второй раз в ответ на ответ Марка Гравелла.

Ответы [ 2 ]

4 голосов
/ 29 июня 2011

Короткая версия - , которая уже должна работать ; на основании ошибки:

Тип: SMDApp.Models.CagedAnimal не поддерживается dapper

Я заключаю, что либо вы фактически передаете new {cagedAnimal} вместо cagedAnimal, или , ваш CagedAnimal имеет свойство (Parent, возможно?), Которое само по себе CagedAnimal и какой изумительный не может понять. Текущее поведение заключается в том, что параметр добавляется для каждого открытого свойства предоставленного объекта параметра - и если он не может выяснить, как отправить какое-либо из свойств в базу данных, это жалуется. Вы должны обнаружить, что простой POCO с только что значимыми членами работает нормально.

Однако! Обратите внимание, что он никогда не пытается проанализировать ваш SQL - в частности, он не проверяет параметры в предоставленном запросе. Таким образом, использование подхода POCO будет означать, что вы добавляете ненужные свойства в запрос.

Мы широко используем dapper и просто используем подход:

 new { obj.Foo, obj.Bar, id, key = "something else" }
3 голосов
/ 29 июня 2011

Марк только что внес изменение в исправление этой проблемы , в частности:

  1. Мы выполняем тривиальную проверку перед отправкой, пытаясь перевести свойства в params. Например, Dapper не будет отправлять какие-либо параметры на сервер в этом случае: cnn.Query ("select 1", new {bla = 1}), поскольку в строке не существует "bla" Эта проверка пропускается для сохраненных процедур.

  2. Ошибка, которая была довольно загадочной, теперь исправлена ​​и значительно улучшена.

-

Даппер раньше не выполнял синтаксический анализ основного оператора SQL, например:

@"select * 
from animal
where animalid = @AnimalId"

Содержит один параметр с именем @AnimalId.

Это становится сложной причиной, чтобы быть на 100% правильным, вам нужно обрабатывать крайние случаи. Например: @AnimalId в строку select '@AnimalId' -- @AnimalId \* @AnimalId *\? Регулярное выражение становится немного хитрым, я не продумал все возможные варианты. Например: Oracle префикс своих параметров с :, что еще больше усложняет.

Поскольку dapper ничего не знал о параметрах в строке, он решил отправить каждое открытое свойство в качестве параметра. Некоторые из ваших общедоступных свойств не могут быть сопоставлены с DbParameters, поэтому он пожаловался.

...