Как сопоставить отношения объектов с помощью Dapper в ASP.NET Core

автор vadim


Dapper — это простой, легкий и по праву популярный ORM (сопоставитель объектных отношений) для .NET. Основы работы с Dapper мы узнали в предыдущей статье. Работу с библиотекой Dapper Extensions мы обсуждали в предыдущей статье. Совсем недавно мы исследовали несколько расширенных функций Dapper.

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

Чтобы использовать примеры кода, представленные в этой статье, в вашей системе должна быть установлена ​​Visual Studio 2022. Если у вас еще нет копии, вы можете скачать Visual Studio 2022 здесь.

Создайте проект веб-API ASP.NET Core в Visual Studio.

Прежде всего давайте создадим проект ASP.NET Core 7 в Visual Studio 2022. Выполните следующие шаги:

  1. Запустите интегрированную среду разработки Visual Studio 2022.
  2. Нажмите «Создать новый проект».
  3. В окне «Создать новый проект» выберите «ASP.NET Core Web API» из списка отображаемых шаблонов.
  4. Нажмите “Далее.
  5. В окне «Настроить новый проект» укажите имя и местоположение нового проекта.
  6. При желании установите флажок «Поместить решение и проект в один каталог», в зависимости от ваших предпочтений.
  7. Нажмите “Далее.
  8. В следующем окне «Дополнительная информация» оставьте флажок «Использовать контроллеры (снимите флажок, чтобы использовать минимальные API)». В этом проекте мы не будем использовать минимальные API. Оставьте для параметра «Тип аутентификации» значение «Нет» (по умолчанию).
  9. Убедитесь, что флажки «Включить поддержку Open API», «Настроить HTTPS» и «Включить Docker» остаются снятыми. Мы не будем использовать эти функции здесь.
  10. Нажмите Создать.

Мы будем использовать этот проект веб-API ASP.NET Core 7 для работы с расширенными функциями Dapper в разделах ниже.

Что такое Даппер? Зачем его использовать?

Объектно-реляционные преобразователи используются для устранения «несоответствия импеданса» между объектными моделями в языках программирования и моделями данных в реляционных базах данных. Dapper — это легкая, высокопроизводительная платформа микро-ORM для .NET и .NET Core. Он поддерживает широкий спектр баз данных, таких как Oracle, SQL Server, Oracle, MySQL, PostgreSQL, SQLite и SQL CE. Команда Stack Overflow создала Dapper как простую ORM для .NET. Dapper — проект с открытым исходным кодом, доступный на GitHub.

Мультимаппинг в Dapper

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

Для этого вы используете параметр SplitOn при вызове метода Query Dapper. Метод SplitOn указывает, какие столбцы следует использовать для разделения данных на несколько объектов. Рассмотрим следующие два класса.

public class Author {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Book {
    public int Id { get; set; }
    public int AuthorId { get; set; }
    public string Title { get; set; }
    public string ISBN { get; set; }
}

Следующий фрагмент кода показывает, как можно реализовать множественное сопоставление с помощью Dapper.

using (var connection = new SqlConnection(connectionString)){
    string query = "SELECT * from Authors A Inner Join Books B ON A.Id = B.AuthorId";
    var authors = connection.Query<Author, Book, Author>(
        query,
        (author, book) =>
        {
            author.Books = author.Books ?? new List<Book>();
            author.Books.Add(book);
        },
    splitOn: "Id"        
    ).Distinct().ToList();
}

Простое картографирование в Dapper

Рассмотрим таблицу базы данных с именем Store с полями, перечисленными в таблице ниже.

Имя таблицы: Магазин

Имя поля

Тип поля

Store_Id (Primary_Key)

Целое число (генерируется автоматически)

Название магазина

Варчар

Расположение

Варчар

Следующий параметризованный запрос SQL вернет запись из таблицы базы данных Store, имеющую соответствующий Store_Id:

Select Store_Id, Store_Name, Location
From Store Where Store_Id = @StoreId 

Чтобы получить запись из таблицы базы данных Store с помощью Dapper, используйте следующий фрагмент кода.

using var connection = new SqlConnection();
var stores = await connection.QueryAsync<Store>(
    sql, new { Store_Id = storeId });

Мультисопоставление отношений один-к-одному в Dapper

Рассмотрим две таблицы базы данных с именами «Заказ» и «Клиент» с полями, перечисленными в таблицах ниже.

Имя таблицы: Заказ

Имя поля

Тип поля

Order_Id (Primary_Key)

Целое число (генерируется автоматически)

Customer_Id (Foreign_Key)

Целое число

Дата заказа

ДатаВремя

Заказанное Количество

Целое число

Стоимость заказа

Двойной

Имя таблицы: Клиент

Имя поля

Тип поля

Customer_Id (Primary_Key)

Целое число (генерируется автоматически)

Имя

Варчар

Фамилия

Варчар

Адрес

Варчар

Телефон

Варчар

Электронная почта

Варчар

Вы можете использовать следующий SQL-запрос, чтобы выбрать запись заказа и связанные с ней сведения о клиенте.

Select o.Order_Id, o.Order_Date, c.Customer_Id, c.First_Name, c.Last_Name
From Order o
Inner Join Customer c On o.Customer_Id = c.Customer_Id

В следующем коде показано, как можно установить взаимно однозначное сопоставление между таблицами базы данных Order и Customer и получить записи Order с помощью Dapper.

string query = "Select * From Order o Inner Join Customer c On o.Customer_Id = c.Customer_Id";
var orders = connection.Query<Order, Customer, Order>(query, map:
    (order, customer) =>
    {
      order.Customer = customer;
      return order;
    }, splitOn: "Customer_Id").FirstOrDefault();

Мультисопоставление отношений «один-ко-многим» в Dapper

Теперь мы изменим таблицу Order, включив в нее дополнительное поле. Следующие таблицы базы данных иллюстрируют связь «один ко многим» между двумя объектами: «Заказ» и «Продукт». Это означает, что вы можете иметь заказ, связанный с несколькими продуктами.

Имя таблицы: Заказ

Имя поля

Тип поля

Order_Id (Primary_Key)

Целое число (генерируется автоматически)

Product_Id (Foreign_Key)

Целое число

Customer_Id (Foreign_Key)

Целое число

Дата заказа

ДатаВремя

Заказанное Количество

Целое число

Стоимость заказа

Двойной

Имя таблицы: Продукт

Имя поля

Тип поля

Product_Id (Primary_Key)

Целое число (генерируется автоматически)

Наименование товара

Варчар

Продукт_Количество

Целое число

Цена за единицу товара

Двойной

Теперь вы можете использовать следующий SQL-запрос для получения всех заказов.

Select Order_Id, Order_Quantity, Order_Date, p.Product_Name
From Order o
Inner Join Product p On o.Product_Id = p.Product_Id

В следующем фрагменте кода показано, как установить сопоставление «один ко многим» между таблицами Order и Product и получить записи Order с помощью Dapper.

string query = "Select * From Order o Inner Join Product p On o.Product_Id = p.Product_Id";
var orders = connection.Query<Order, Product, Order>(query, map:
    (order, product) =>
    {
      order.Product = product;
      return order;
    }, splitOn: "Product_Id;

Мультисопоставление отношений «многие ко многим» в Dapper

Отношения «многие ко многим» немного сложнее. Например, у вас может быть связь между сущностями «Студент» и «Курс», где один студент может записаться на несколько курсов, а вы также можете сопоставить один курс нескольким студентам. Другими словами, отношения «многие ко многим» позволяют связать несколько записей в одной таблице с несколькими записями в другой таблице.

Такие отношения обычно реализуются с помощью третьей таблицы, которую иногда называют «соединительной таблицей» или «мостовой таблицей». Чтобы отобразить связь «многие ко многим» с помощью Dapper, вы должны обработать таблицу соединений и выполнить несколько SQL-запросов или один хорошо составленный запрос для получения связанных данных.

Рассмотрим три таблицы базы данных с именами Student, Course и StudentCourse и их соответствующие поля, как показано в таблицах ниже.

Название таблицы: Студент

Имя поля

Тип поля

Student_Id (Primary_Key)

Целое число (генерируется автоматически)

Имя

Варчар

Фамилия

Варчар

Адрес

Варчар

Название таблицы: Курс

Имя поля

Тип поля

Course_Id (Primary_Key)

Целое число (генерируется автоматически)

Название курса

Варчар

Длительность курса

Целое число

Дата начала

ДатаВремя

Имя таблицы: Student_Course

Имя поля

Тип поля

Student_Course_Id (Primary_Key)

Целое число (генерируется автоматически)

Student_Id (Foreign_Key)

Целое число

Course_Id (Foreign_Key)

Целое число

Мы можем представить отношения между студентами и курсами, используя следующие классы.

public class Student
    {
        public int Student_Id { get; private set; }
        public string FirstName { get; set; } = string.Empty;
        public string LastName { get; set; }
        public string Address { get; set; } = string.Empty;
        public List<Course> Courses { get; set; }
    }
    public class Course
    {
        public int Course_Id { get; private set; }
        public string Course_Title { get; set; }
        public int Course_Duration { get; set; } 
        public DateTime Start_Date { get; set; }
  public List<Student> Courses { get; set; }
    }

Обратите внимание на списки в классах «Студент» и «Курс». Класс Student содержит список курсов, а класс Course содержит список студентов. Вы можете использовать следующий оператор SQL для получения студента и связанных с ним данных.

Select s.Student_Id, s.First_Name, s.Last_Name, c.Course_Title
From Student s
Inner Join Student_Course sc ON sc.Student_Id = s.Student_Id
Inner Join Course c ON c.Course_Id = sc.Course_Id

Вы можете установить сопоставление «многие ко многим» между объектами «Студент» и «Курс» в Dapper, что позволит вам получать записи студентов вместе с курсами, на которые они зарегистрировались. Вот код:

using(var connection = new SqlConnection(connectionString))
{
  string query = "Select s.Student_Id, s.First_Name, s.Last_Name, c.Course_Title From Student s " +
    "Inner Join Student_Course sc ON sc.Student_Id = s.Student_Id " +
    "Inner Join Course c ON c.Course_Id = sc.Course_Id";
  var students = await connection.QueryAsync <Student,
    Course, Student > (query, (student, course) => {
      student.Courses.Add(course);
      return student;
    }, splitOn: "Course_Id");
}

Dapper — это легкая, производительная и настраиваемая ORM с отличными функциями, которые могут значительно улучшить возможности доступа к данным в ваших приложениях .NET Core. Как мы видели, Dapper обеспечивает отличную поддержку для отображения отношений. Подробнее об использовании Dapper я расскажу в следующей статье.

Дальше читайте это:

  • Облачные вычисления больше не являются пустяком
  • Что такое генеративный ИИ? Искусственный интеллект, который создает
  • Программирование с помощью ИИ: советы и лучшие практики от разработчиков
  • Python пытается удалить GIL и повысить параллелизм
  • 7 причин, по которым Java по-прежнему хороша
  • Война за лицензирование открытого исходного кода окончена

Related Posts

Оставить комментарий