Расширение Dapper: класс с составными полями, сопоставленными с отдельной таблицей.

У меня есть следующие классы:

public class Publication
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Headline { get; set; }
    public DateTime Published { get; set; }
    public ProductContact Contact { get; set; }
}

public class ProductContact
{
    public string FullName { get; set; }
    public string JobTitle { get; set; }
    public string Email { get; set; }
}

И таблица, связанная с этой структурой, «Публикации», имеет все эти поля (включая свойства ProductContact).

Если я попытаюсь вставить строку публикации (с включенной информацией ProductContact), программа выдаст исключение:

System.NotSupportedException: The member Contact of type ProductContact cannot be used as a parameter value

Итак, я добавил сопоставитель для сопоставления свойств ProductContact с полями в таблице свойств:

  public PublicationMapper ()
    {
        TableName = "Publications";

        Map(x => x.Contact.FullName).Column("ContactFullName");
        Map(x => x.Contact.JobTitle).Column("ContactJobTitle");
        Map(x => x.Contact.Email).Column("ContactEmail");

        AutoMap();
    }

С этим картографом я получаю то же исключение.

Затем я добавил оператор ignore для поля «Контакт», чтобы Dapper не включал этот элемент в оператор вставки.

            Map(x => x.Contact).Ignore();

В этом случае я получаю другое исключение:

System.Data.SqlClient.SqlException (0x80131904): Must declare the scalar variable "@FullName".

Это указывает на то, что Dapper полностью игнорирует это свойство, и сопоставление, добавленное на предыдущем шаге, не действует.

Есть ли способ сопоставить свойства ProductContact с полями таблицы?

Спасибо.


person ggimenez    schedule 06.07.2016    source источник
comment
Почему не просто анонимный класс new { pub.Id, pub.Title,......, ContactFullName = pub.Contact.FullName, ContactJobTitle = pub.Contact.JobTitle,ContactEmail = pub.Contact.Email}? Хотя звучит так, будто ContactFullName на самом деле должно быть просто FullName, чтобы соответствовать имени параметра в вашем SQL. Здесь также поможет отображение SQL и полного вызова Dapper.   -  person juharr    schedule 06.07.2016
comment
Жаль, что он не может/не будет этого делать. Я оказался в нужном месте, пытаясь показать руководству, что Dapper — это путь к сокращению кода и простоте использования. Особенно, когда объекты и их аналоги данных имеют разные имена. Ах хорошо   -  person zerohero    schedule 02.08.2017


Ответы (1)


Я не думаю, что это возможно с DapperExtensions.

В одной из своих задач они говорят

В настоящее время мы не планируем поддерживать вложенные объекты. Однако вы можете создать свой собственный Mapper, который позволит пропустить вложенный объект.

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

Одним из подходов может быть ручное сведение вашего объекта в анонимный класс (как было предложено @juharr в комментарии к вашему вопросу), другим подходом может быть использование чего-то вроде AutoMapper для сглаживания вашего сложного объекта в сглаженную модель вставки.

person Dan Roberts    schedule 07.07.2016