Жестко закодированные запросы SQL и код жесткого доступа к данным могут затруднить масштабирование или переключение баз данных, и они часто приводят к повторяемой логике.
Copilot Chat может рекомендовать реализацию шаблона репозитория или уровня доступа к данным, который абстрагирует взаимодействие с базой данных, что делает код более модульным и уменьшающим избыточность. Кроме того, он может помочь рефакторингу запросов SQL в оптимизированные версии, повысить производительность и удобство обслуживания.
Note
Ответы, описанные в этой статье, являются примерами. Ответы Copilot Chat являются недетерминированными, поэтому вы можете получить различные ответы, показанные здесь.
Пример сценария
Этот код Python подключается к базе данных SQLite, извлекает запись пользователя и возвращает данные пользователя. Однако она не может абстрагировать логику подключения к базе данных и использует жестко закодированный запрос, который уязвим для внедрения SQL.
import sqlite3
def get_user_by_id(user_id):
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
cursor.execute(f"SELECT display_name FROM users WHERE id = {user_id}")
user = cursor.fetchone()
conn.close()
return user
Пример запроса 1
Для начала можно задать Copilot общий вопрос о том, как улучшить код.
How can I improve this code to make it safe and easier to update and expand? List possible improvements but don't show revised code.
Пример ответа 1
Copilot предлагает несколько предложений по улучшению кода:
- Абстрагирование сведений о подключении к базе данных.
- Используйте параметризованные запросы, чтобы предотвратить внедрение SQL.
- Используйте диспетчер контекстов, чтобы убедиться, что подключение к базе данных правильно закрыто при возникновении ошибки.
- Добавьте обработку ошибок.
Пример запроса 2
Вы можете использовать ответ на первый запрос, чтобы написать более конкретный запрос.
Rewrite this code to make it more scalable and easier to maintain. Use a context manager. Avoid hardcoded SQL queries and tightly coupled data access code. Instead, use a repository pattern to abstract database interactions and make the code more modular and reusable. Where possible optimize the code to improve performance. Include error trapping, and make sure the code is not vulnerable to SQL injection.
Пример ответа 2
Copilot предлагает разделить код на отдельные файлы, каждый из которых имеет определенную цель. Он также содержит пример кода для возврата сведений о пользователе.
Предлагаемые изменения реализуют шаблон репозитория и используют параметризованные запросы, чтобы избежать внедрения SQL.
# database.py
import sqlite3
class Database:
def __init__(self, db_path):
self.db_path = db_path
def __enter__(self):
self.conn = sqlite3.connect(self.db_path)
self.cursor = self.conn.cursor()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type or exc_val or exc_tb:
self.conn.rollback()
else:
self.conn.commit()
self.conn.close()
# user_repository.py
class UserRepository:
def __init__(self, db):
self.db = db
def get_user_by_id(self, user_id):
try:
self.db.cursor.execute("SELECT display_name FROM users WHERE id = ?", (user_id,))
user = self.db.cursor.fetchone()
return user
except sqlite3.Error as e:
print(f"An error occurred: {e}")
return None
# main.py
from database import Database
from user_repository import UserRepository
def get_user_by_id(user_id):
with Database('database.db') as db:
user_repo = UserRepository(db)
return user_repo.get_user_by_id(user_id)
# Example usage
if __name__ == "__main__":
user = get_user_by_id(1)
if user:
print(user)
else:
print("User not found or an error occurred.")
Измененный код улучшает исходный код несколькими способами:
- Теперь код реализует базовый уровень доступа к данным.
- Класс
Database
обрабатывает подключение к базе данных SQLite, реализуя протокол диспетчера контекстов с__enter__
помощью методов и__exit__
методов. Это гарантирует правильное управление подключением к базе данных, включая фиксацию транзакций и закрытие подключения. - Класс
UserRepository
инкапсулирует логику доступа к данным пользователя. - Значения запросов параметризованы, чтобы предотвратить внедрение SQL.
- Ошибки перехватываются с подробными сведениями, напечатанными в консоли.