Initial commit: ADO.NET Lab Application

This commit is contained in:
Student 2026-10-05 06:02:05 +05:00
commit 551f5e3977
96 changed files with 4644 additions and 0 deletions

3
AdoNetShop.slnx Normal file
View File

@ -0,0 +1,3 @@
<Solution>
<Project Path="AdoNetShop/AdoNetShop.csproj" />
</Solution>

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1,38 @@
using System.Data;
using AdoNetShop.Models;
using Microsoft.Data.SqlClient;
namespace AdoNetShop.Data;
public class CategoryRepository
{
private readonly DbConnectionFactory _connectionFactory;
public CategoryRepository(DbConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
public async Task<List<Category>> GetAllAsync()
{
var categories = new List<Category>();
await using var connection = _connectionFactory.CreateConnection();
await connection.OpenAsync();
string query = "SELECT Id, Name FROM Categories";
await using var command = new SqlCommand(query, connection);
await using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
categories.Add(new Category
{
Id = reader.GetInt32(0),
Name = reader.GetString(1)
});
}
return categories;
}
}

View File

@ -0,0 +1,40 @@
using System.Data;
using AdoNetShop.Models;
using Microsoft.Data.SqlClient;
namespace AdoNetShop.Data;
public class CustomerRepository
{
private readonly DbConnectionFactory _connectionFactory;
public CustomerRepository(DbConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
public async Task<List<Customer>> GetAllAsync()
{
var customers = new List<Customer>();
await using var connection = _connectionFactory.CreateConnection();
await connection.OpenAsync();
string query = "SELECT Id, Name, Email, Phone FROM Customers";
await using var command = new SqlCommand(query, connection);
await using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
customers.Add(new Customer
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Email = reader.GetString(2),
Phone = reader.IsDBNull(3) ? null : reader.GetString(3)
});
}
return customers;
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;
namespace AdoNetShop.Data;
public class DbConnectionFactory
{
private readonly string _connectionString;
public DbConnectionFactory(IConfiguration configuration)
{
// Получаем строку подключения из конфигурации (appsettings.json)
_connectionString = configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
}
// Фабричный метод для создания и настройки подключения
public SqlConnection CreateConnection()
{
return new SqlConnection(_connectionString);
}
}

View File

@ -0,0 +1,117 @@
using System.Data;
using AdoNetShop.Models;
using Microsoft.Data.SqlClient;
namespace AdoNetShop.Data;
public class OrderRepository
{
private readonly DbConnectionFactory _connectionFactory;
public OrderRepository(DbConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
// Демонстрация транзакции (Создание заказа)
public async Task<int> CreateOrderWithTransactionAsync(Order order)
{
await using var connection = _connectionFactory.CreateConnection();
await connection.OpenAsync();
// 1. Начинаем транзакцию
await using var transaction = (SqlTransaction)await connection.BeginTransactionAsync();
try
{
// 2. Создаем сам заказ
string insertOrderQuery = @"
INSERT INTO Orders (CustomerId, OrderDate, Status, TotalAmount)
VALUES (@CustomerId, @OrderDate, @Status, @TotalAmount);
SELECT SCOPE_IDENTITY();";
await using var insertOrderCommand = new SqlCommand(insertOrderQuery, connection, transaction);
insertOrderCommand.Parameters.Add("@CustomerId", SqlDbType.Int).Value = order.CustomerId;
insertOrderCommand.Parameters.Add("@OrderDate", SqlDbType.DateTime2).Value = order.OrderDate;
insertOrderCommand.Parameters.Add("@Status", SqlDbType.NVarChar, 50).Value = order.Status;
insertOrderCommand.Parameters.Add("@TotalAmount", SqlDbType.Decimal).Value = order.TotalAmount;
var newOrderIdObj = await insertOrderCommand.ExecuteScalarAsync();
if (newOrderIdObj == null) throw new Exception("Failed to create order.");
int newOrderId = Convert.ToInt32(newOrderIdObj);
// 3. Добавляем товары заказа и обновляем остатки
string insertItemQuery = @"
INSERT INTO OrderItems (OrderId, ProductId, Quantity, Price)
VALUES (@OrderId, @ProductId, @Quantity, @Price)";
string updateStockQuery = @"
UPDATE Products
SET StockQuantity = StockQuantity - @Quantity
WHERE Id = @ProductId AND StockQuantity >= @Quantity";
foreach (var item in order.Items)
{
// Проверка наличия и уменьшение остатка
await using var updateStockCommand = new SqlCommand(updateStockQuery, connection, transaction);
updateStockCommand.Parameters.Add("@ProductId", SqlDbType.Int).Value = item.ProductId;
updateStockCommand.Parameters.Add("@Quantity", SqlDbType.Int).Value = item.Quantity;
int rowsAffected = await updateStockCommand.ExecuteNonQueryAsync();
if (rowsAffected == 0)
{
// Если обновление не удалось (недостаточно товара или неверный ID),
// генерируем исключение. Это приведет к переходу в блок catch и откату транзакции.
throw new Exception($"Недостаточно товара на складе для ProductId: {item.ProductId}");
}
// Добавление позиции заказа
await using var insertItemCommand = new SqlCommand(insertItemQuery, connection, transaction);
insertItemCommand.Parameters.Add("@OrderId", SqlDbType.Int).Value = newOrderId;
insertItemCommand.Parameters.Add("@ProductId", SqlDbType.Int).Value = item.ProductId;
insertItemCommand.Parameters.Add("@Quantity", SqlDbType.Int).Value = item.Quantity;
insertItemCommand.Parameters.Add("@Price", SqlDbType.Decimal).Value = item.Price;
await insertItemCommand.ExecuteNonQueryAsync();
}
// 4. Если всё прошло успешно, фиксируем транзакцию
await transaction.CommitAsync();
return newOrderId;
}
catch (Exception ex)
{
// 5. При возникновении любой ошибки откатываем транзакцию
// Все изменения (созданный заказ, измененные остатки) будут отменены
await transaction.RollbackAsync();
// Пробрасываем ошибку дальше для обработки на уровне UI/Сервиса
throw new Exception($"Ошибка при создании заказа. Транзакция отменена. Детали: {ex.Message}", ex);
}
}
// Получение списка заказов (простая реализация)
public async Task<List<Order>> GetAllOrdersBasicAsync()
{
var orders = new List<Order>();
await using var connection = _connectionFactory.CreateConnection();
await connection.OpenAsync();
string query = "SELECT Id, CustomerId, OrderDate, Status, TotalAmount FROM Orders";
await using var command = new SqlCommand(query, connection);
await using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
orders.Add(new Order
{
Id = reader.GetInt32(0),
CustomerId = reader.GetInt32(1),
OrderDate = reader.GetDateTime(2),
Status = reader.GetString(3),
TotalAmount = reader.GetDecimal(4)
});
}
return orders;
}
}

View File

@ -0,0 +1,163 @@
using System.Data;
using AdoNetShop.Models;
using Microsoft.Data.SqlClient;
namespace AdoNetShop.Data;
public class ProductRepository
{
private readonly DbConnectionFactory _connectionFactory;
public ProductRepository(DbConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
// CRUD: Read All (Получение списка)
public async Task<List<Product>> GetAllAsync()
{
var products = new List<Product>();
// Используем await using для автоматического освобождения ресурсов
await using var connection = _connectionFactory.CreateConnection();
await connection.OpenAsync(); // Открываем подключение
string query = "SELECT Id, Name, Description, Price, StockQuantity, CategoryId FROM Products";
await using var command = new SqlCommand(query, connection);
// SqlDataReader обеспечивает потоковое чтение результатов (forward-only)
await using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
products.Add(new Product
{
Id = reader.GetInt32(reader.GetOrdinal("Id")),
Name = reader.GetString(reader.GetOrdinal("Name")),
// Обработка возможного NULL значения для Description
Description = reader.IsDBNull(reader.GetOrdinal("Description")) ? null : reader.GetString(reader.GetOrdinal("Description")),
Price = reader.GetDecimal(reader.GetOrdinal("Price")),
StockQuantity = reader.GetInt32(reader.GetOrdinal("StockQuantity")),
CategoryId = reader.GetInt32(reader.GetOrdinal("CategoryId"))
});
}
return products;
}
// CRUD: Read One (Получение одного товара по ID)
public async Task<Product?> GetByIdAsync(int id)
{
await using var connection = _connectionFactory.CreateConnection();
await connection.OpenAsync();
// Использование параметров для предотвращения SQL Injections
string query = "SELECT Id, Name, Description, Price, StockQuantity, CategoryId FROM Products WHERE Id = @Id";
await using var command = new SqlCommand(query, connection);
command.Parameters.Add("@Id", SqlDbType.Int).Value = id;
await using var reader = await command.ExecuteReaderAsync();
if (await reader.ReadAsync())
{
return new Product
{
Id = reader.GetInt32(reader.GetOrdinal("Id")),
Name = reader.GetString(reader.GetOrdinal("Name")),
Description = reader.IsDBNull(reader.GetOrdinal("Description")) ? null : reader.GetString(reader.GetOrdinal("Description")),
Price = reader.GetDecimal(reader.GetOrdinal("Price")),
StockQuantity = reader.GetInt32(reader.GetOrdinal("StockQuantity")),
CategoryId = reader.GetInt32(reader.GetOrdinal("CategoryId"))
};
}
return null; // Если товар не найден
}
// CRUD: Create (Добавление)
public async Task<int> CreateAsync(Product product)
{
await using var connection = _connectionFactory.CreateConnection();
await connection.OpenAsync();
// Используем OUTPUT INSERTED.Id или SCOPE_IDENTITY() для получения сгенерированного Id
string query = @"
INSERT INTO Products (Name, Description, Price, StockQuantity, CategoryId)
VALUES (@Name, @Description, @Price, @StockQuantity, @CategoryId);
SELECT SCOPE_IDENTITY();";
await using var command = new SqlCommand(query, connection);
// Явное указание типов параметров (хорошая практика)
command.Parameters.Add("@Name", SqlDbType.NVarChar, 200).Value = product.Name;
command.Parameters.Add("@Description", SqlDbType.NVarChar, -1).Value = (object?)product.Description ?? DBNull.Value;
command.Parameters.Add("@Price", SqlDbType.Decimal).Value = product.Price;
command.Parameters.Add("@StockQuantity", SqlDbType.Int).Value = product.StockQuantity;
command.Parameters.Add("@CategoryId", SqlDbType.Int).Value = product.CategoryId;
// ExecuteScalarAsync используется для получения единственного значения (в данном случае Id)
var newId = await command.ExecuteScalarAsync();
return Convert.ToInt32(newId);
}
// CRUD: Update (Обновление)
public async Task<bool> UpdateAsync(Product product)
{
await using var connection = _connectionFactory.CreateConnection();
await connection.OpenAsync();
string query = @"
UPDATE Products
SET Name = @Name, Description = @Description, Price = @Price,
StockQuantity = @StockQuantity, CategoryId = @CategoryId
WHERE Id = @Id";
await using var command = new SqlCommand(query, connection);
command.Parameters.Add("@Id", SqlDbType.Int).Value = product.Id;
command.Parameters.Add("@Name", SqlDbType.NVarChar, 200).Value = product.Name;
command.Parameters.Add("@Description", SqlDbType.NVarChar, -1).Value = (object?)product.Description ?? DBNull.Value;
command.Parameters.Add("@Price", SqlDbType.Decimal).Value = product.Price;
command.Parameters.Add("@StockQuantity", SqlDbType.Int).Value = product.StockQuantity;
command.Parameters.Add("@CategoryId", SqlDbType.Int).Value = product.CategoryId;
// ExecuteNonQueryAsync используется для запросов INSERT/UPDATE/DELETE
int rowsAffected = await command.ExecuteNonQueryAsync();
return rowsAffected > 0;
}
// CRUD: Delete (Удаление)
public async Task<bool> DeleteAsync(int id)
{
await using var connection = _connectionFactory.CreateConnection();
await connection.OpenAsync();
string query = "DELETE FROM Products WHERE Id = @Id";
await using var command = new SqlCommand(query, connection);
command.Parameters.Add("@Id", SqlDbType.Int).Value = id;
int rowsAffected = await command.ExecuteNonQueryAsync();
return rowsAffected > 0;
}
// Демонстрация DataAdapter и автономной модели (Disconnected Mode)
public async Task<DataTable> GetProductsTableAsync()
{
await using var connection = _connectionFactory.CreateConnection();
string query = "SELECT Id, Name, Price, StockQuantity FROM Products";
await using var command = new SqlCommand(query, connection);
// SqlDataAdapter служит мостом между БД и DataSet/DataTable
using var adapter = new SqlDataAdapter(command);
var table = new DataTable("Products");
// Метод Fill открывает подключение (если оно закрыто), выполняет запрос,
// заполняет DataTable и закрывает подключение (если оно было закрыто).
// Это и есть автономный режим.
await Task.Run(() => adapter.Fill(table));
return table;
}
}

View File

@ -0,0 +1,7 @@
namespace AdoNetShop.Models;
public class Category
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}

View File

@ -0,0 +1,9 @@
namespace AdoNetShop.Models;
public class Customer
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string? Phone { get; set; }
}

View File

@ -0,0 +1,12 @@
namespace AdoNetShop.Models;
public class Order
{
public int Id { get; set; }
public int CustomerId { get; set; }
public DateTime OrderDate { get; set; }
public string Status { get; set; } = "New";
public decimal TotalAmount { get; set; }
public List<OrderItem> Items { get; set; } = new List<OrderItem>();
}

View File

@ -0,0 +1,10 @@
namespace AdoNetShop.Models;
public class OrderItem
{
public int Id { get; set; }
public int OrderId { get; set; }
public int ProductId { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace AdoNetShop.Models;
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? Description { get; set; }
public decimal Price { get; set; }
public int StockQuantity { get; set; }
public int CategoryId { get; set; }
// Навигационное свойство (заполняется опционально)
public Category? Category { get; set; }
}

297
AdoNetShop/Program.cs Normal file
View File

@ -0,0 +1,297 @@
using System.Data;
using AdoNetShop.Data;
using AdoNetShop.Models;
using AdoNetShop.Services;
using Microsoft.Extensions.Configuration;
namespace AdoNetShop;
class Program
{
static async Task Main(string[] args)
{
// 1. Настройка конфигурации для чтения appsettings.json
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
// 2. "Ручной" Dependency Injection
var connectionFactory = new DbConnectionFactory(configuration);
var productRepo = new ProductRepository(connectionFactory);
var categoryRepo = new CategoryRepository(connectionFactory);
var customerRepo = new CustomerRepository(connectionFactory);
var orderRepo = new OrderRepository(connectionFactory);
var shopService = new ShopService(productRepo, categoryRepo, customerRepo, orderRepo);
// 3. Главный цикл приложения
bool exit = false;
while (!exit)
{
Console.Clear();
Console.WriteLine("================================");
Console.WriteLine(" ADO.NET SHOP");
Console.WriteLine("================================");
Console.WriteLine("1. Список товаров");
Console.WriteLine("2. Найти товар по ID");
Console.WriteLine("3. Добавить товар");
Console.WriteLine("4. Изменить товар");
Console.WriteLine("5. Удалить товар");
Console.WriteLine("6. Список категорий");
Console.WriteLine("7. Список клиентов");
Console.WriteLine("8. Создать заказ (Демонстрация Transaction)");
Console.WriteLine("9. Просмотреть заказы");
Console.WriteLine("10. Демонстрация DataAdapter (Disconnected mode)");
Console.WriteLine("0. Выход");
Console.WriteLine("================================");
Console.Write("Выберите действие: ");
var input = Console.ReadLine();
try
{
switch (input)
{
case "1":
await ShowAllProducts(shopService);
break;
case "2":
await FindProduct(shopService);
break;
case "3":
await AddProduct(shopService);
break;
case "4":
await UpdateProduct(shopService);
break;
case "5":
await DeleteProduct(shopService);
break;
case "6":
await ShowAllCategories(shopService);
break;
case "7":
await ShowAllCustomers(shopService);
break;
case "8":
await CreateOrder(shopService);
break;
case "9":
await ShowAllOrders(shopService);
break;
case "10":
await DemoDataAdapter(shopService);
break;
case "0":
exit = true;
break;
default:
Console.WriteLine("Неверный ввод.");
break;
}
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"\n[ОШИБКА]: {ex.Message}");
if(ex.InnerException != null)
{
Console.WriteLine($"[ДЕТАЛИ]: {ex.InnerException.Message}");
}
Console.ResetColor();
}
if (!exit)
{
Console.WriteLine("\nНажмите любую клавишу для продолжения...");
Console.ReadKey();
}
}
}
private static async Task ShowAllProducts(ShopService service)
{
Console.WriteLine("\n--- Список товаров ---");
var products = await service.GetAllProductsAsync();
foreach (var p in products)
{
Console.WriteLine($"[{p.Id}] {p.Name} | Цена: {p.Price:C} | Остаток: {p.StockQuantity} | Кат: {p.CategoryId}");
}
}
private static async Task FindProduct(ShopService service)
{
Console.Write("\nВведите ID товара: ");
if (int.TryParse(Console.ReadLine(), out int id))
{
var product = await service.GetProductByIdAsync(id);
if (product != null)
{
Console.WriteLine($"Найдено: [{product.Id}] {product.Name} - {product.Description} | {product.Price:C} | {product.StockQuantity} шт.");
}
else
{
Console.WriteLine("Товар не найден.");
}
}
else
{
Console.WriteLine("Некорректный ID.");
}
}
private static async Task AddProduct(ShopService service)
{
Console.WriteLine("\n--- Добавление товара ---");
Console.Write("Название: ");
string name = Console.ReadLine() ?? "";
Console.Write("Описание: ");
string desc = Console.ReadLine() ?? "";
Console.Write("Цена: ");
if (!decimal.TryParse(Console.ReadLine(), out decimal price)) throw new ArgumentException("Неверный формат цены.");
Console.Write("Количество: ");
if (!int.TryParse(Console.ReadLine(), out int quantity)) throw new ArgumentException("Неверный формат количества.");
Console.Write("ID Категории: ");
if (!int.TryParse(Console.ReadLine(), out int catId)) throw new ArgumentException("Неверный формат ID категории.");
var product = new Product
{
Name = name,
Description = desc,
Price = price,
StockQuantity = quantity,
CategoryId = catId
};
int newId = await service.CreateProductAsync(product);
Console.WriteLine($"Товар успешно добавлен. Новый ID: {newId}");
}
private static async Task UpdateProduct(ShopService service)
{
Console.Write("\nВведите ID товара для обновления: ");
if (!int.TryParse(Console.ReadLine(), out int id)) return;
var product = await service.GetProductByIdAsync(id);
if (product == null)
{
Console.WriteLine("Товар не найден.");
return;
}
Console.WriteLine($"Текущее название: {product.Name}");
Console.Write("Новое название (оставьте пустым, чтобы не менять): ");
string name = Console.ReadLine() ?? "";
if (!string.IsNullOrWhiteSpace(name)) product.Name = name;
Console.WriteLine($"Текущая цена: {product.Price}");
Console.Write("Новая цена (оставьте пустым, чтобы не менять): ");
string priceStr = Console.ReadLine() ?? "";
if (!string.IsNullOrWhiteSpace(priceStr) && decimal.TryParse(priceStr, out decimal price)) product.Price = price;
bool updated = await service.UpdateProductAsync(product);
Console.WriteLine(updated ? "Товар обновлен." : "Не удалось обновить товар.");
}
private static async Task DeleteProduct(ShopService service)
{
Console.Write("\nВведите ID товара для удаления: ");
if (int.TryParse(Console.ReadLine(), out int id))
{
bool deleted = await service.DeleteProductAsync(id);
Console.WriteLine(deleted ? "Товар удален." : "Товар не найден или не может быть удален.");
}
}
private static async Task ShowAllCategories(ShopService service)
{
Console.WriteLine("\n--- Категории ---");
var cats = await service.GetAllCategoriesAsync();
foreach (var c in cats) Console.WriteLine($"[{c.Id}] {c.Name}");
}
private static async Task ShowAllCustomers(ShopService service)
{
Console.WriteLine("\n--- Клиенты ---");
var customers = await service.GetAllCustomersAsync();
foreach (var c in customers) Console.WriteLine($"[{c.Id}] {c.Name} ({c.Email})");
}
private static async Task CreateOrder(ShopService service)
{
Console.WriteLine("\n--- Создание заказа ---");
await ShowAllCustomers(service);
Console.Write("Введите ID клиента: ");
if (!int.TryParse(Console.ReadLine(), out int customerId)) return;
var items = new List<(int ProductId, int Quantity)>();
while (true)
{
Console.Write("Введите ID товара (или 0 для завершения): ");
if (!int.TryParse(Console.ReadLine(), out int productId)) continue;
if (productId == 0) break;
Console.Write("Введите количество: ");
if (!int.TryParse(Console.ReadLine(), out int quantity) || quantity <= 0)
{
Console.WriteLine("Неверное количество.");
continue;
}
items.Add((productId, quantity));
}
if (items.Count == 0)
{
Console.WriteLine("Заказ отменен (нет товаров).");
return;
}
Console.WriteLine("Попытка создать заказ в БД (Транзакция)...");
int orderId = await service.CreateOrderAsync(customerId, items);
Console.WriteLine($"Заказ успешно создан! ID: {orderId}");
}
private static async Task ShowAllOrders(ShopService service)
{
Console.WriteLine("\n--- Заказы ---");
var orders = await service.GetAllOrdersAsync();
foreach (var o in orders)
{
Console.WriteLine($"[{o.Id}] Клиент: {o.CustomerId} | Сумма: {o.TotalAmount:C} | Дата: {o.OrderDate:g} | Статус: {o.Status}");
}
}
private static async Task DemoDataAdapter(ShopService service)
{
Console.WriteLine("\n--- Демонстрация DataAdapter (Disconnected mode) ---");
Console.WriteLine("Запрашиваем данные через DataAdapter.Fill()...");
DataTable table = await service.GetProductsTableAsync();
Console.WriteLine($"Получено строк: {table.Rows.Count}");
Console.WriteLine("Подключение к БД уже закрыто. Данные находятся в памяти (DataTable).\n");
Console.WriteLine("Id\tName\t\t\tPrice");
Console.WriteLine("--------------------------------------------------");
// Чтение данных из автономного DataTable
foreach (DataRow row in table.Rows)
{
int id = (int)row["Id"];
string name = (string)row["Name"];
decimal price = (decimal)row["Price"];
Console.WriteLine($"{id}\t{name,-20}\t{price:C}");
}
}
}

View File

@ -0,0 +1,92 @@
using AdoNetShop.Data;
using AdoNetShop.Models;
namespace AdoNetShop.Services;
// Сервисы могут содержать дополнительную бизнес-логику,
// но в рамках этой лабы они выступают простыми прокси к репозиториям.
public class ShopService
{
private readonly ProductRepository _productRepository;
private readonly CategoryRepository _categoryRepository;
private readonly CustomerRepository _customerRepository;
private readonly OrderRepository _orderRepository;
public ShopService(
ProductRepository productRepository,
CategoryRepository categoryRepository,
CustomerRepository customerRepository,
OrderRepository orderRepository)
{
_productRepository = productRepository;
_categoryRepository = categoryRepository;
_customerRepository = customerRepository;
_orderRepository = orderRepository;
}
public Task<List<Product>> GetAllProductsAsync() => _productRepository.GetAllAsync();
public Task<Product?> GetProductByIdAsync(int id) => _productRepository.GetByIdAsync(id);
public async Task<int> CreateProductAsync(Product product)
{
// Пример простой валидации на уровне сервиса
if (product.Price <= 0) throw new ArgumentException("Price must be greater than 0");
if (product.StockQuantity < 0) throw new ArgumentException("Stock cannot be negative");
return await _productRepository.CreateAsync(product);
}
public Task<bool> UpdateProductAsync(Product product) => _productRepository.UpdateAsync(product);
public Task<bool> DeleteProductAsync(int id) => _productRepository.DeleteAsync(id);
public Task<List<Category>> GetAllCategoriesAsync() => _categoryRepository.GetAllAsync();
public Task<List<Customer>> GetAllCustomersAsync() => _customerRepository.GetAllAsync();
public async Task<int> CreateOrderAsync(int customerId, List<(int ProductId, int Quantity)> requestedItems)
{
// 1. Формируем заказ
var order = new Order
{
CustomerId = customerId,
OrderDate = DateTime.Now,
Status = "Created",
Items = new List<OrderItem>()
};
decimal totalAmount = 0;
// 2. Получаем актуальные цены товаров
foreach (var reqItem in requestedItems)
{
var product = await _productRepository.GetByIdAsync(reqItem.ProductId);
if (product == null)
{
throw new ArgumentException($"Product with ID {reqItem.ProductId} not found.");
}
if(product.StockQuantity < reqItem.Quantity)
{
throw new ArgumentException($"Not enough stock for product '{product.Name}'. Available: {product.StockQuantity}, Requested: {reqItem.Quantity}");
}
var orderItem = new OrderItem
{
ProductId = reqItem.ProductId,
Quantity = reqItem.Quantity,
Price = product.Price
};
order.Items.Add(orderItem);
totalAmount += (reqItem.Quantity * product.Price);
}
order.TotalAmount = totalAmount;
// 3. Вызываем репозиторий для сохранения (внутри будет транзакция)
return await _orderRepository.CreateOrderWithTransactionAsync(order);
}
public Task<List<Order>> GetAllOrdersAsync() => _orderRepository.GetAllOrdersBasicAsync();
public Task<System.Data.DataTable> GetProductsTableAsync() => _productRepository.GetProductsTableAsync();
}

View File

@ -0,0 +1,5 @@
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=AdoNetShop;Trusted_Connection=True;TrustServerCertificate=True;"
}
}

View File

@ -0,0 +1,634 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v8.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v8.0": {
"AdoNetShop/1.0.0": {
"dependencies": {
"Microsoft.Data.SqlClient": "5.2.0",
"Microsoft.Extensions.Configuration": "8.0.0",
"Microsoft.Extensions.Configuration.Binder": "8.0.1",
"Microsoft.Extensions.Configuration.Json": "8.0.0"
},
"runtime": {
"AdoNetShop.dll": {}
}
},
"Azure.Core/1.35.0": {
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "1.1.1",
"System.Memory.Data": "1.0.2"
},
"runtime": {
"lib/net6.0/Azure.Core.dll": {
"assemblyVersion": "1.35.0.0",
"fileVersion": "1.3500.23.45706"
}
}
},
"Azure.Identity/1.10.3": {
"dependencies": {
"Azure.Core": "1.35.0",
"Microsoft.Identity.Client": "4.56.0",
"Microsoft.Identity.Client.Extensions.Msal": "4.56.0",
"System.Security.Cryptography.ProtectedData": "8.0.0"
},
"runtime": {
"lib/netstandard2.0/Azure.Identity.dll": {
"assemblyVersion": "1.10.3.0",
"fileVersion": "1.1000.323.51804"
}
}
},
"Microsoft.Bcl.AsyncInterfaces/1.1.1": {
"runtime": {
"lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "4.700.20.21406"
}
}
},
"Microsoft.Data.SqlClient/5.2.0": {
"dependencies": {
"Azure.Identity": "1.10.3",
"Microsoft.Data.SqlClient.SNI.runtime": "5.2.0",
"Microsoft.Identity.Client": "4.56.0",
"Microsoft.IdentityModel.JsonWebTokens": "6.35.0",
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.35.0",
"Microsoft.SqlServer.Server": "1.0.0",
"System.Configuration.ConfigurationManager": "8.0.0",
"System.Runtime.Caching": "8.0.0"
},
"runtime": {
"lib/net8.0/Microsoft.Data.SqlClient.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.20.24059.2"
}
},
"resources": {
"lib/net8.0/de/Microsoft.Data.SqlClient.resources.dll": {
"locale": "de"
},
"lib/net8.0/es/Microsoft.Data.SqlClient.resources.dll": {
"locale": "es"
},
"lib/net8.0/fr/Microsoft.Data.SqlClient.resources.dll": {
"locale": "fr"
},
"lib/net8.0/it/Microsoft.Data.SqlClient.resources.dll": {
"locale": "it"
},
"lib/net8.0/ja/Microsoft.Data.SqlClient.resources.dll": {
"locale": "ja"
},
"lib/net8.0/ko/Microsoft.Data.SqlClient.resources.dll": {
"locale": "ko"
},
"lib/net8.0/pt-BR/Microsoft.Data.SqlClient.resources.dll": {
"locale": "pt-BR"
},
"lib/net8.0/ru/Microsoft.Data.SqlClient.resources.dll": {
"locale": "ru"
},
"lib/net8.0/zh-Hans/Microsoft.Data.SqlClient.resources.dll": {
"locale": "zh-Hans"
},
"lib/net8.0/zh-Hant/Microsoft.Data.SqlClient.resources.dll": {
"locale": "zh-Hant"
}
},
"runtimeTargets": {
"runtimes/unix/lib/net8.0/Microsoft.Data.SqlClient.dll": {
"rid": "unix",
"assetType": "runtime",
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.20.24059.2"
},
"runtimes/win/lib/net8.0/Microsoft.Data.SqlClient.dll": {
"rid": "win",
"assetType": "runtime",
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.20.24059.2"
}
}
},
"Microsoft.Data.SqlClient.SNI.runtime/5.2.0": {
"runtimeTargets": {
"runtimes/win-arm/native/Microsoft.Data.SqlClient.SNI.dll": {
"rid": "win-arm",
"assetType": "native",
"fileVersion": "5.2.0.0"
},
"runtimes/win-arm64/native/Microsoft.Data.SqlClient.SNI.dll": {
"rid": "win-arm64",
"assetType": "native",
"fileVersion": "5.2.0.0"
},
"runtimes/win-x64/native/Microsoft.Data.SqlClient.SNI.dll": {
"rid": "win-x64",
"assetType": "native",
"fileVersion": "5.2.0.0"
},
"runtimes/win-x86/native/Microsoft.Data.SqlClient.SNI.dll": {
"rid": "win-x86",
"assetType": "native",
"fileVersion": "5.2.0.0"
}
}
},
"Microsoft.Extensions.Configuration/8.0.0": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "8.0.0",
"Microsoft.Extensions.Primitives": "8.0.0"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.Configuration.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Extensions.Configuration.Abstractions/8.0.0": {
"dependencies": {
"Microsoft.Extensions.Primitives": "8.0.0"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Extensions.Configuration.Binder/8.0.1": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "8.0.0"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.Configuration.Binder.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.123.58001"
}
}
},
"Microsoft.Extensions.Configuration.FileExtensions/8.0.0": {
"dependencies": {
"Microsoft.Extensions.Configuration": "8.0.0",
"Microsoft.Extensions.Configuration.Abstractions": "8.0.0",
"Microsoft.Extensions.FileProviders.Abstractions": "8.0.0",
"Microsoft.Extensions.FileProviders.Physical": "8.0.0",
"Microsoft.Extensions.Primitives": "8.0.0"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.Configuration.FileExtensions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Extensions.Configuration.Json/8.0.0": {
"dependencies": {
"Microsoft.Extensions.Configuration": "8.0.0",
"Microsoft.Extensions.Configuration.Abstractions": "8.0.0",
"Microsoft.Extensions.Configuration.FileExtensions": "8.0.0",
"Microsoft.Extensions.FileProviders.Abstractions": "8.0.0"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.Configuration.Json.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Extensions.FileProviders.Abstractions/8.0.0": {
"dependencies": {
"Microsoft.Extensions.Primitives": "8.0.0"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.FileProviders.Abstractions.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Extensions.FileProviders.Physical/8.0.0": {
"dependencies": {
"Microsoft.Extensions.FileProviders.Abstractions": "8.0.0",
"Microsoft.Extensions.FileSystemGlobbing": "8.0.0",
"Microsoft.Extensions.Primitives": "8.0.0"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.FileProviders.Physical.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Extensions.FileSystemGlobbing/8.0.0": {
"runtime": {
"lib/net8.0/Microsoft.Extensions.FileSystemGlobbing.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Extensions.Primitives/8.0.0": {
"runtime": {
"lib/net8.0/Microsoft.Extensions.Primitives.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Identity.Client/4.56.0": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "6.35.0"
},
"runtime": {
"lib/net6.0/Microsoft.Identity.Client.dll": {
"assemblyVersion": "4.56.0.0",
"fileVersion": "4.56.0.0"
}
}
},
"Microsoft.Identity.Client.Extensions.Msal/4.56.0": {
"dependencies": {
"Microsoft.Identity.Client": "4.56.0",
"System.Security.Cryptography.ProtectedData": "8.0.0"
},
"runtime": {
"lib/netstandard2.0/Microsoft.Identity.Client.Extensions.Msal.dll": {
"assemblyVersion": "4.56.0.0",
"fileVersion": "4.56.0.0"
}
}
},
"Microsoft.IdentityModel.Abstractions/6.35.0": {
"runtime": {
"lib/net6.0/Microsoft.IdentityModel.Abstractions.dll": {
"assemblyVersion": "6.35.0.0",
"fileVersion": "6.35.0.41201"
}
}
},
"Microsoft.IdentityModel.JsonWebTokens/6.35.0": {
"dependencies": {
"Microsoft.IdentityModel.Tokens": "6.35.0"
},
"runtime": {
"lib/net6.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
"assemblyVersion": "6.35.0.0",
"fileVersion": "6.35.0.41201"
}
}
},
"Microsoft.IdentityModel.Logging/6.35.0": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "6.35.0"
},
"runtime": {
"lib/net6.0/Microsoft.IdentityModel.Logging.dll": {
"assemblyVersion": "6.35.0.0",
"fileVersion": "6.35.0.41201"
}
}
},
"Microsoft.IdentityModel.Protocols/6.35.0": {
"dependencies": {
"Microsoft.IdentityModel.Logging": "6.35.0",
"Microsoft.IdentityModel.Tokens": "6.35.0"
},
"runtime": {
"lib/net6.0/Microsoft.IdentityModel.Protocols.dll": {
"assemblyVersion": "6.35.0.0",
"fileVersion": "6.35.0.41201"
}
}
},
"Microsoft.IdentityModel.Protocols.OpenIdConnect/6.35.0": {
"dependencies": {
"Microsoft.IdentityModel.Protocols": "6.35.0",
"System.IdentityModel.Tokens.Jwt": "6.35.0"
},
"runtime": {
"lib/net6.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": {
"assemblyVersion": "6.35.0.0",
"fileVersion": "6.35.0.41201"
}
}
},
"Microsoft.IdentityModel.Tokens/6.35.0": {
"dependencies": {
"Microsoft.IdentityModel.Logging": "6.35.0"
},
"runtime": {
"lib/net6.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "6.35.0.0",
"fileVersion": "6.35.0.41201"
}
}
},
"Microsoft.SqlServer.Server/1.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.SqlServer.Server.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"System.Configuration.ConfigurationManager/8.0.0": {
"dependencies": {
"System.Diagnostics.EventLog": "8.0.0",
"System.Security.Cryptography.ProtectedData": "8.0.0"
},
"runtime": {
"lib/net8.0/System.Configuration.ConfigurationManager.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"System.Diagnostics.EventLog/8.0.0": {
"runtime": {
"lib/net8.0/System.Diagnostics.EventLog.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
},
"runtimeTargets": {
"runtimes/win/lib/net8.0/System.Diagnostics.EventLog.Messages.dll": {
"rid": "win",
"assetType": "runtime",
"assemblyVersion": "8.0.0.0",
"fileVersion": "0.0.0.0"
},
"runtimes/win/lib/net8.0/System.Diagnostics.EventLog.dll": {
"rid": "win",
"assetType": "runtime",
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"System.IdentityModel.Tokens.Jwt/6.35.0": {
"dependencies": {
"Microsoft.IdentityModel.JsonWebTokens": "6.35.0",
"Microsoft.IdentityModel.Tokens": "6.35.0"
},
"runtime": {
"lib/net6.0/System.IdentityModel.Tokens.Jwt.dll": {
"assemblyVersion": "6.35.0.0",
"fileVersion": "6.35.0.41201"
}
}
},
"System.Memory.Data/1.0.2": {
"runtime": {
"lib/netstandard2.0/System.Memory.Data.dll": {
"assemblyVersion": "1.0.2.0",
"fileVersion": "1.0.221.20802"
}
}
},
"System.Runtime.Caching/8.0.0": {
"dependencies": {
"System.Configuration.ConfigurationManager": "8.0.0"
},
"runtime": {
"lib/net8.0/System.Runtime.Caching.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
},
"runtimeTargets": {
"runtimes/win/lib/net8.0/System.Runtime.Caching.dll": {
"rid": "win",
"assetType": "runtime",
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"System.Security.Cryptography.ProtectedData/8.0.0": {
"runtime": {
"lib/net8.0/System.Security.Cryptography.ProtectedData.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
}
}
},
"libraries": {
"AdoNetShop/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Azure.Core/1.35.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-hENcx03Jyuqv05F4RBEPbxz29UrM3Nbhnr6Wl6NQpoU9BCIbL3XLentrxDCTrH54NLS11Exxi/o8MYgT/cnKFA==",
"path": "azure.core/1.35.0",
"hashPath": "azure.core.1.35.0.nupkg.sha512"
},
"Azure.Identity/1.10.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-l1Xm2MWOF2Mzcwuarlw8kWQXLZk3UeB55aQXVyjj23aBfDwOZ3gu5GP2kJ6KlmZeZv2TCzw7x4L3V36iNr3gww==",
"path": "azure.identity/1.10.3",
"hashPath": "azure.identity.1.10.3.nupkg.sha512"
},
"Microsoft.Bcl.AsyncInterfaces/1.1.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==",
"path": "microsoft.bcl.asyncinterfaces/1.1.1",
"hashPath": "microsoft.bcl.asyncinterfaces.1.1.1.nupkg.sha512"
},
"Microsoft.Data.SqlClient/5.2.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3alfyqRN3ELRtdvU1dGtLBRNQqprr3TJ0WrUJfMISPwg1nPUN2P3Lelah68IKWuV27Ceb7ig95hWNHFTSXfxMg==",
"path": "microsoft.data.sqlclient/5.2.0",
"hashPath": "microsoft.data.sqlclient.5.2.0.nupkg.sha512"
},
"Microsoft.Data.SqlClient.SNI.runtime/5.2.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-po1jhvFd+8pbfvJR/puh+fkHi0GRanAdvayh/0e47yaM6CXWZ6opUjCMFuYlAnD2LcbyvQE7fPJKvogmaUcN+w==",
"path": "microsoft.data.sqlclient.sni.runtime/5.2.0",
"hashPath": "microsoft.data.sqlclient.sni.runtime.5.2.0.nupkg.sha512"
},
"Microsoft.Extensions.Configuration/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==",
"path": "microsoft.extensions.configuration/8.0.0",
"hashPath": "microsoft.extensions.configuration.8.0.0.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Abstractions/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==",
"path": "microsoft.extensions.configuration.abstractions/8.0.0",
"hashPath": "microsoft.extensions.configuration.abstractions.8.0.0.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Binder/8.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-2UKFJnLiBt7Od6nCnTqP9rTIUNhzmn9Hv1l2FchyKbz8xieB9ULwZTbQZMw+M24Qw3F5dzzH1U9PPleN0LNLOQ==",
"path": "microsoft.extensions.configuration.binder/8.0.1",
"hashPath": "microsoft.extensions.configuration.binder.8.0.1.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.FileExtensions/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-McP+Lz/EKwvtCv48z0YImw+L1gi1gy5rHhNaNIY2CrjloV+XY8gydT8DjMR6zWeL13AFK+DioVpppwAuO1Gi1w==",
"path": "microsoft.extensions.configuration.fileextensions/8.0.0",
"hashPath": "microsoft.extensions.configuration.fileextensions.8.0.0.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Json/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-C2wqUoh9OmRL1akaCcKSTmRU8z0kckfImG7zLNI8uyi47Lp+zd5LWAD17waPQEqCz3ioWOCrFUo+JJuoeZLOBw==",
"path": "microsoft.extensions.configuration.json/8.0.0",
"hashPath": "microsoft.extensions.configuration.json.8.0.0.nupkg.sha512"
},
"Microsoft.Extensions.FileProviders.Abstractions/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==",
"path": "microsoft.extensions.fileproviders.abstractions/8.0.0",
"hashPath": "microsoft.extensions.fileproviders.abstractions.8.0.0.nupkg.sha512"
},
"Microsoft.Extensions.FileProviders.Physical/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==",
"path": "microsoft.extensions.fileproviders.physical/8.0.0",
"hashPath": "microsoft.extensions.fileproviders.physical.8.0.0.nupkg.sha512"
},
"Microsoft.Extensions.FileSystemGlobbing/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==",
"path": "microsoft.extensions.filesystemglobbing/8.0.0",
"hashPath": "microsoft.extensions.filesystemglobbing.8.0.0.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==",
"path": "microsoft.extensions.primitives/8.0.0",
"hashPath": "microsoft.extensions.primitives.8.0.0.nupkg.sha512"
},
"Microsoft.Identity.Client/4.56.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rr4zbidvHy9r4NvOAs5hdd964Ao2A0pAeFBJKR95u1CJAVzbd1p6tPTXUZ+5ld0cfThiVSGvz6UHwY6JjraTpA==",
"path": "microsoft.identity.client/4.56.0",
"hashPath": "microsoft.identity.client.4.56.0.nupkg.sha512"
},
"Microsoft.Identity.Client.Extensions.Msal/4.56.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-H12YAzEGK55vZ+QpxUzozhW8ZZtgPDuWvgA0JbdIR9UhMUplj29JhIgE2imuH8W2Nw9D8JKygR1uxRFtpSNcrg==",
"path": "microsoft.identity.client.extensions.msal/4.56.0",
"hashPath": "microsoft.identity.client.extensions.msal.4.56.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Abstractions/6.35.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-xuR8E4Rd96M41CnUSCiOJ2DBh+z+zQSmyrYHdYhD6K4fXBcQGVnRCFQ0efROUYpP+p0zC1BLKr0JRpVuujTZSg==",
"path": "microsoft.identitymodel.abstractions/6.35.0",
"hashPath": "microsoft.identitymodel.abstractions.6.35.0.nupkg.sha512"
},
"Microsoft.IdentityModel.JsonWebTokens/6.35.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-9wxai3hKgZUb4/NjdRKfQd0QJvtXKDlvmGMYACbEC8DFaicMFCFhQFZq9ZET1kJLwZahf2lfY5Gtcpsx8zYzbg==",
"path": "microsoft.identitymodel.jsonwebtokens/6.35.0",
"hashPath": "microsoft.identitymodel.jsonwebtokens.6.35.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Logging/6.35.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-jePrSfGAmqT81JDCNSY+fxVWoGuJKt9e6eJ+vT7+quVS55nWl//jGjUQn4eFtVKt4rt5dXaleZdHRB9J9AJZ7Q==",
"path": "microsoft.identitymodel.logging/6.35.0",
"hashPath": "microsoft.identitymodel.logging.6.35.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Protocols/6.35.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BPQhlDzdFvv1PzaUxNSk+VEPwezlDEVADIKmyxubw7IiELK18uJ06RQ9QKKkds30XI+gDu9n8j24XQ8w7fjWcg==",
"path": "microsoft.identitymodel.protocols/6.35.0",
"hashPath": "microsoft.identitymodel.protocols.6.35.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Protocols.OpenIdConnect/6.35.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LMtVqnECCCdSmyFoCOxIE5tXQqkOLrvGrL7OxHg41DIm1bpWtaCdGyVcTAfOQpJXvzND9zUKIN/lhngPkYR8vg==",
"path": "microsoft.identitymodel.protocols.openidconnect/6.35.0",
"hashPath": "microsoft.identitymodel.protocols.openidconnect.6.35.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Tokens/6.35.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-RN7lvp7s3Boucg1NaNAbqDbxtlLj5Qeb+4uSS1TeK5FSBVM40P4DKaTKChT43sHyKfh7V0zkrMph6DdHvyA4bg==",
"path": "microsoft.identitymodel.tokens/6.35.0",
"hashPath": "microsoft.identitymodel.tokens.6.35.0.nupkg.sha512"
},
"Microsoft.SqlServer.Server/1.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==",
"path": "microsoft.sqlserver.server/1.0.0",
"hashPath": "microsoft.sqlserver.server.1.0.0.nupkg.sha512"
},
"System.Configuration.ConfigurationManager/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JlYi9XVvIREURRUlGMr1F6vOFLk7YSY4p1vHo4kX3tQ0AGrjqlRWHDi66ImHhy6qwXBG3BJ6Y1QlYQ+Qz6Xgww==",
"path": "system.configuration.configurationmanager/8.0.0",
"hashPath": "system.configuration.configurationmanager.8.0.0.nupkg.sha512"
},
"System.Diagnostics.EventLog/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==",
"path": "system.diagnostics.eventlog/8.0.0",
"hashPath": "system.diagnostics.eventlog.8.0.0.nupkg.sha512"
},
"System.IdentityModel.Tokens.Jwt/6.35.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-yxGIQd3BFK7F6S62/7RdZk3C/mfwyVxvh6ngd1VYMBmbJ1YZZA9+Ku6suylVtso0FjI0wbElpJ0d27CdsyLpBQ==",
"path": "system.identitymodel.tokens.jwt/6.35.0",
"hashPath": "system.identitymodel.tokens.jwt.6.35.0.nupkg.sha512"
},
"System.Memory.Data/1.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==",
"path": "system.memory.data/1.0.2",
"hashPath": "system.memory.data.1.0.2.nupkg.sha512"
},
"System.Runtime.Caching/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==",
"path": "system.runtime.caching/8.0.0",
"hashPath": "system.runtime.caching.8.0.0.nupkg.sha512"
},
"System.Security.Cryptography.ProtectedData/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg==",
"path": "system.security.cryptography.protecteddata/8.0.0",
"hashPath": "system.security.cryptography.protecteddata.8.0.0.nupkg.sha512"
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,12 @@
{
"runtimeOptions": {
"tfm": "net8.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "8.0.0"
},
"configProperties": {
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,5 @@
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=AdoNetShop;Trusted_Connection=True;TrustServerCertificate=True;"
}
}

View File

@ -0,0 +1,112 @@
{
"format": 1,
"restore": {
"C:\\Users\\ivaiv\\OneDrive\\Desktop\\Artem\\AdoNetShop\\AdoNetShop.csproj": {}
},
"projects": {
"C:\\Users\\ivaiv\\OneDrive\\Desktop\\Artem\\AdoNetShop\\AdoNetShop.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "C:\\Users\\ivaiv\\OneDrive\\Desktop\\Artem\\AdoNetShop\\AdoNetShop.csproj",
"projectName": "AdoNetShop",
"projectPath": "C:\\Users\\ivaiv\\OneDrive\\Desktop\\Artem\\AdoNetShop\\AdoNetShop.csproj",
"packagesPath": "C:\\Users\\ivaiv\\.nuget\\packages\\",
"outputPath": "C:\\Users\\ivaiv\\OneDrive\\Desktop\\Artem\\AdoNetShop\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\ivaiv\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"C:\\Program Files\\dotnet\\library-packs": {},
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"framework": "net8.0",
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "10.0.400"
},
"frameworks": {
"net8.0": {
"framework": "net8.0",
"targetAlias": "net8.0",
"dependencies": {
"Microsoft.Data.SqlClient": {
"target": "Package",
"version": "[5.2.0, )"
},
"Microsoft.Extensions.Configuration": {
"target": "Package",
"version": "[8.0.0, )"
},
"Microsoft.Extensions.Configuration.Binder": {
"target": "Package",
"version": "[8.0.1, )"
},
"Microsoft.Extensions.Configuration.Json": {
"target": "Package",
"version": "[8.0.0, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.30, 8.0.30]"
},
{
"name": "Microsoft.NETCore.App.Host.win-x64",
"version": "[8.0.30, 8.0.30]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.30, 8.0.30]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.30, 8.0.30]"
}
],
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.400/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\ivaiv\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\ivaiv\.nuget\packages\" />
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)system.text.json\8.0.0\buildTransitive\net6.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\8.0.0\buildTransitive\net6.0\System.Text.Json.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.1\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.1\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" />
</ImportGroup>
</Project>

View File

@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]

View File

@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("AdoNetShop")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("AdoNetShop")]
[assembly: System.Reflection.AssemblyTitleAttribute("AdoNetShop")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

View File

@ -0,0 +1 @@
edcaefc3f74c59b79e27cc94850e594ffc6716212f1a49064e94007b5ff80557

View File

@ -0,0 +1,18 @@
is_global = true
build_property.TargetFramework = net8.0
build_property.TargetFrameworkIdentifier = .NETCoreApp
build_property.TargetFrameworkVersion = v8.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property.EntryPointFilePath =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = AdoNetShop
build_property.ProjectDir = C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View File

@ -0,0 +1,8 @@
// <auto-generated/>
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Net.Http;
global using System.Threading;
global using System.Threading.Tasks;

Binary file not shown.

View File

@ -0,0 +1 @@
c5616ae976ba3d611b5e228dd7cefa521620c5f6c068aa1cf7ad4b73c787d851

View File

@ -0,0 +1,64 @@
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\appsettings.json
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\AdoNetShop.exe
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\AdoNetShop.deps.json
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\AdoNetShop.runtimeconfig.json
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\AdoNetShop.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\AdoNetShop.pdb
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Azure.Core.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Azure.Identity.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Bcl.AsyncInterfaces.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Data.SqlClient.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Extensions.Configuration.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Extensions.Configuration.Abstractions.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Extensions.Configuration.Binder.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Extensions.Configuration.FileExtensions.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Extensions.Configuration.Json.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Extensions.FileProviders.Abstractions.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Extensions.FileProviders.Physical.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Extensions.FileSystemGlobbing.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Extensions.Primitives.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Identity.Client.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.Identity.Client.Extensions.Msal.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.IdentityModel.Abstractions.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.IdentityModel.JsonWebTokens.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.IdentityModel.Logging.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.IdentityModel.Protocols.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.IdentityModel.Tokens.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\Microsoft.SqlServer.Server.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\System.Configuration.ConfigurationManager.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\System.Diagnostics.EventLog.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\System.IdentityModel.Tokens.Jwt.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\System.Memory.Data.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\System.Runtime.Caching.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\System.Security.Cryptography.ProtectedData.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\de\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\es\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\fr\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\it\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\ja\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\ko\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\pt-BR\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\ru\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\zh-Hans\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\zh-Hant\Microsoft.Data.SqlClient.resources.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\runtimes\unix\lib\net8.0\Microsoft.Data.SqlClient.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\runtimes\win\lib\net8.0\Microsoft.Data.SqlClient.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\runtimes\win-arm\native\Microsoft.Data.SqlClient.SNI.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\runtimes\win-arm64\native\Microsoft.Data.SqlClient.SNI.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\runtimes\win-x64\native\Microsoft.Data.SqlClient.SNI.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\runtimes\win-x86\native\Microsoft.Data.SqlClient.SNI.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\runtimes\win\lib\net8.0\System.Diagnostics.EventLog.Messages.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\runtimes\win\lib\net8.0\System.Diagnostics.EventLog.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\bin\Debug\net8.0\runtimes\win\lib\net8.0\System.Runtime.Caching.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\AdoNetShop.csproj.AssemblyReference.cache
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\AdoNetShop.GeneratedMSBuildEditorConfig.editorconfig
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\AdoNetShop.AssemblyInfoInputs.cache
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\AdoNetShop.AssemblyInfo.cs
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\AdoNetShop.csproj.CoreCompileInputs.cache
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\AdoNetShop.csproj.Up2Date
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\AdoNetShop.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\refint\AdoNetShop.dll
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\AdoNetShop.pdb
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\AdoNetShop.genruntimeconfig.cache
C:\Users\ivaiv\OneDrive\Desktop\Artem\AdoNetShop\obj\Debug\net8.0\ref\AdoNetShop.dll

Binary file not shown.

View File

@ -0,0 +1 @@
a4c2f57a00f5817125eb18d0619c0cb75bf436e1533456138e024ef72518b8ce

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
{
"version": 2,
"dgSpecHash": "zA1M7STRDRY=",
"success": true,
"projectFilePath": "C:\\Users\\ivaiv\\OneDrive\\Desktop\\Artem\\AdoNetShop\\AdoNetShop.csproj",
"expectedPackageFiles": [
"C:\\Users\\ivaiv\\.nuget\\packages\\azure.core\\1.35.0\\azure.core.1.35.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\azure.identity\\1.10.3\\azure.identity.1.10.3.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.bcl.asyncinterfaces\\1.1.1\\microsoft.bcl.asyncinterfaces.1.1.1.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.csharp\\4.5.0\\microsoft.csharp.4.5.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.data.sqlclient\\5.2.0\\microsoft.data.sqlclient.5.2.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.data.sqlclient.sni.runtime\\5.2.0\\microsoft.data.sqlclient.sni.runtime.5.2.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.extensions.configuration\\8.0.0\\microsoft.extensions.configuration.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.extensions.configuration.abstractions\\8.0.0\\microsoft.extensions.configuration.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.extensions.configuration.binder\\8.0.1\\microsoft.extensions.configuration.binder.8.0.1.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.extensions.configuration.fileextensions\\8.0.0\\microsoft.extensions.configuration.fileextensions.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.extensions.configuration.json\\8.0.0\\microsoft.extensions.configuration.json.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.extensions.fileproviders.abstractions\\8.0.0\\microsoft.extensions.fileproviders.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.extensions.fileproviders.physical\\8.0.0\\microsoft.extensions.fileproviders.physical.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.extensions.filesystemglobbing\\8.0.0\\microsoft.extensions.filesystemglobbing.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.extensions.primitives\\8.0.0\\microsoft.extensions.primitives.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.identity.client\\4.56.0\\microsoft.identity.client.4.56.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.identity.client.extensions.msal\\4.56.0\\microsoft.identity.client.extensions.msal.4.56.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.identitymodel.abstractions\\6.35.0\\microsoft.identitymodel.abstractions.6.35.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.identitymodel.jsonwebtokens\\6.35.0\\microsoft.identitymodel.jsonwebtokens.6.35.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.identitymodel.logging\\6.35.0\\microsoft.identitymodel.logging.6.35.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.identitymodel.protocols\\6.35.0\\microsoft.identitymodel.protocols.6.35.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.identitymodel.protocols.openidconnect\\6.35.0\\microsoft.identitymodel.protocols.openidconnect.6.35.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.identitymodel.tokens\\6.35.0\\microsoft.identitymodel.tokens.6.35.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.netcore.platforms\\5.0.0\\microsoft.netcore.platforms.5.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.netcore.targets\\1.1.0\\microsoft.netcore.targets.1.1.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.sqlserver.server\\1.0.0\\microsoft.sqlserver.server.1.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.configuration.configurationmanager\\8.0.0\\system.configuration.configurationmanager.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.diagnostics.diagnosticsource\\6.0.1\\system.diagnostics.diagnosticsource.6.0.1.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.diagnostics.eventlog\\8.0.0\\system.diagnostics.eventlog.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.identitymodel.tokens.jwt\\6.35.0\\system.identitymodel.tokens.jwt.6.35.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.io.filesystem.accesscontrol\\5.0.0\\system.io.filesystem.accesscontrol.5.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.memory\\4.5.4\\system.memory.4.5.4.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.memory.data\\1.0.2\\system.memory.data.1.0.2.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.numerics.vectors\\4.5.0\\system.numerics.vectors.4.5.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.runtime\\4.3.0\\system.runtime.4.3.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.runtime.caching\\8.0.0\\system.runtime.caching.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.runtime.compilerservices.unsafe\\6.0.0\\system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.security.accesscontrol\\5.0.0\\system.security.accesscontrol.5.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.security.cryptography.cng\\4.5.0\\system.security.cryptography.cng.4.5.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.security.cryptography.protecteddata\\8.0.0\\system.security.cryptography.protecteddata.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.security.principal.windows\\5.0.0\\system.security.principal.windows.5.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.text.encoding\\4.3.0\\system.text.encoding.4.3.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.text.encodings.web\\8.0.0\\system.text.encodings.web.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.text.json\\8.0.0\\system.text.json.8.0.0.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\system.threading.tasks.extensions\\4.5.4\\system.threading.tasks.extensions.4.5.4.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.netcore.app.ref\\8.0.30\\microsoft.netcore.app.ref.8.0.30.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.windowsdesktop.app.ref\\8.0.30\\microsoft.windowsdesktop.app.ref.8.0.30.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.aspnetcore.app.ref\\8.0.30\\microsoft.aspnetcore.app.ref.8.0.30.nupkg.sha512",
"C:\\Users\\ivaiv\\.nuget\\packages\\microsoft.netcore.app.host.win-x64\\8.0.30\\microsoft.netcore.app.host.win-x64.8.0.30.nupkg.sha512"
],
"logs": []
}

74
README.md Normal file
View File

@ -0,0 +1,74 @@
# AdoNetShop: Твоя первая лабораторная по ADO.NET 🎓
Привет! Это учебный проект интернет-магазина. Его главная цель — показать тебе, как работает технология **ADO.NET** изнутри. Мы будем общаться с базой данных Microsoft SQL Server "вручную", без всяких умных прослоек вроде Entity Framework. Это нужно, чтобы ты понял самые основы.
---
## 📚 Немного скучной (но нужной) теории простыми словами
### Что вообще такое ADO.NET?
Представь, что твоя программа (на C#) и база данных (SQL Server) говорят на разных языках и живут в разных городах. ADO.NET — это набор инструментов (переводчиков, почтальонов, телефонов), которые позволяют им общаться.
Мы не используем ORM (Entity Framework), потому что ORM делает всё за тебя "под капотом". В этой лабе мы лезем под капот сами.
### Зачем мы это учим?
1. **Чтобы понимать, как всё работает на самом деле.** Любая крутая ORM в итоге всё равно превращает свой код в команды ADO.NET.
2. **Скорость и контроль.** Иногда нужно написать супер-хитрый и быстрый запрос. Ручной SQL через ADO.NET даст тебе максимальную скорость.
### Главные герои ADO.NET (Что нужно знать для защиты):
* 🔌 **`SqlConnection` (Подключение):** Это твой телефонный провод до базы данных. Чтобы что-то сказать базе, нужно поднять трубку (`Open()`), а потом обязательно положить её (`Close()`, или использовать конструкцию `using`).
* 📝 **`SqlCommand` (Команда):** Это то, *что* ты говоришь в трубку. Обычно это SQL-запросы (`SELECT`, `INSERT` и т.д.).
* 🛡️ **`SqlParameter` (Параметр):** Это твоя защита от злодеев. **Никогда** не склеивай SQL-строку плюсами (типа `"SELECT * FROM Users WHERE Name = " + name`). Хакерам хватит 5 минут, чтобы сломать базу через SQL-инъекцию. Мы передаем переменные *только* через параметры (`@Name`).
* 📖 **`SqlDataReader` (Чтец данных):** Представь, что база диктует тебе длиннющий список товаров по телефону. `DataReader` слушает и записывает строку за строкой. Он работает очень быстро, но *только вперед* и требует, чтобы телефонная линия (Connection) была открыта. (Это называется **Connected** подход).
* 📦 **`SqlDataAdapter` и `DataTable`:** А это другой подход. `DataAdapter` — это курьер. Он сам едет к базе, забирает *все* данные разом, привозит их тебе и кладет в коробку (`DataTable` в памяти компьютера). После этого он сам вешает трубку. Теперь ты можешь ковыряться в этой коробке сколько угодно, не занимая базу данных. (Это называется **Disconnected** подход).
* 🤝 **Транзакция (`SqlTransaction`):** Сделка по принципу "Всё или ничего". Представь перевод денег: списали у тебя, но не зачислили другу. Плохо! Транзакция гарантирует: если база начала делать заказ (создала заказ -> списала товары со склада -> добавила позиции), и вдруг свет моргнул на списании склада — она отменит всё обратно (`Rollback`). Если всё супер — закрепит (`Commit`).
---
## 🚀 Как запустить эту штуку на твоем компе
Чтобы проект заработал, тебе нужны две вещи: работающая база данных и запущенный код.
### Шаг 1: Готовим Базу Данных
1. Убедись, что у тебя установлен **Microsoft SQL Server** (подойдет версия Express) и программа для управления им, например, **SQL Server Management Studio (SSMS)**.
2. Открой папку `database` в этом проекте.
3. Открой SSMS и подключись к своему серверу.
4. Выполни скрипты строго по очереди:
* ▶️ Сначала выполни код из файла `01_create_database.sql` (Это создаст пустую БД).
* ▶️ Затем `02_create_tables.sql` (Создаст нужные таблички).
* ▶️ Затем `03_insert_data.sql` (Заполнит их тестовыми товарами и клиентами).
### Шаг 2: Настраиваем проект
1. Открой файл `AdoNetShop/appsettings.json`.
2. Найди там строку `ConnectionStrings -> DefaultConnection`.
3. Тебе нужно сказать программе, как зовут твой SQL сервер.
* Если у тебя обычный разработческий SQL, оставь `Server=localhost`.
* Если ты ставил SQL Server Express, скорее всего тебе нужно поменять это на `Server=.\\SQLEXPRESS`.
### Шаг 3: Запускаем!
1. Открой терминал (или командную строку) в папке `AdoNetShop` (там, где лежит файл `.csproj`).
2. Напиши команду: `dotnet run`
3. Должно появиться красивое консольное меню магазина.
---
## 👨‍🏫 Что показывать преподавателю на защите?
Препод точно спросит, где и как ты использовал ADO.NET. Вот твоя шпаргалка:
1. **Как ты подключаешься к базе?**
* Покажи файл `Data/DbConnectionFactory.cs`. Расскажи, что строку подключения ты берешь из конфига (это хорошая практика!), а не хардкодишь в коде.
2. **Как работает CRUD (Создание, Чтение, Обновление, Удаление)?**
* Открой `Data/ProductRepository.cs`.
* Покажи метод `GetByIdAsync`. Обрати внимание на `SqlCommand` и то, как ты добавляешь параметры (`command.Parameters.Add`). Расскажи про `SqlDataReader`.
* Покажи метод `CreateAsync`. Обрати внимание на `ExecuteScalarAsync` — объясни, что он нужен, чтобы база вернула тебе ID только что созданного товара.
3. **Где у тебя транзакция?**
* Гордо открывай `Data/OrderRepository.cs` и показывай метод `CreateOrderWithTransactionAsync`.
* Объясни: "Сначала мы открываем транзакцию. Потом пытаемся создать заказ и списать товары. Если хоть одного товара нет на складе, я выбрасываю ошибку, код прыгает в блок `catch`, и делает `RollbackAsync()` — отменяет всё. Если всё гладко — `CommitAsync()`".
* *Для эффекта:* Запусти программу, нажми пункт "8" и попробуй купить 1000 ноутбуков (их столько нет). Покажи, что заказ не создался.
4. **А где Disconnected подход (отсоединенная модель)?**
* Открой пункт меню "10" в запущенной программе.
* Открой метод `GetProductsTableAsync` в `ProductRepository.cs`.
* Покажи класс `SqlDataAdapter` и `DataTable`. Объясни, что курьер (адаптер) сам сбегал в базу, залил всё в таблицу и разорвал связь с БД.
Удачи на защите! Ты справишься! 💪

View File

@ -0,0 +1,11 @@
-- 01_create_database.sql
-- Скрипт для создания базы данных
USE master;
GO
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'AdoNetShop')
BEGIN
CREATE DATABASE [AdoNetShop];
END
GO

View File

@ -0,0 +1,85 @@
-- 02_create_tables.sql
-- Скрипт для создания таблиц
USE [AdoNetShop];
GO
-- Таблица Categories
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Categories')
BEGIN
CREATE TABLE Categories (
Id INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(100) NOT NULL
);
END
GO
-- Таблица Products
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Products')
BEGIN
CREATE TABLE Products (
Id INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(200) NOT NULL,
Description NVARCHAR(MAX) NULL,
Price DECIMAL(18, 2) NOT NULL CHECK (Price > 0),
StockQuantity INT NOT NULL DEFAULT 0 CHECK (StockQuantity >= 0),
CategoryId INT NOT NULL,
FOREIGN KEY (CategoryId) REFERENCES Categories(Id)
);
END
GO
-- Таблица Customers
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Customers')
BEGIN
CREATE TABLE Customers (
Id INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(100) NOT NULL,
Email NVARCHAR(100) NOT NULL UNIQUE,
Phone NVARCHAR(20) NULL
);
END
GO
-- Таблица Orders
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Orders')
BEGIN
CREATE TABLE Orders (
Id INT IDENTITY(1,1) PRIMARY KEY,
CustomerId INT NOT NULL,
OrderDate DATETIME2 NOT NULL DEFAULT GETDATE(),
Status NVARCHAR(50) NOT NULL DEFAULT 'New',
TotalAmount DECIMAL(18, 2) NOT NULL DEFAULT 0 CHECK (TotalAmount >= 0),
FOREIGN KEY (CustomerId) REFERENCES Customers(Id)
);
END
GO
-- Таблица OrderItems
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'OrderItems')
BEGIN
CREATE TABLE OrderItems (
Id INT IDENTITY(1,1) PRIMARY KEY,
OrderId INT NOT NULL,
ProductId INT NOT NULL,
Quantity INT NOT NULL CHECK (Quantity > 0),
Price DECIMAL(18, 2) NOT NULL CHECK (Price > 0),
FOREIGN KEY (OrderId) REFERENCES Orders(Id) ON DELETE CASCADE,
FOREIGN KEY (ProductId) REFERENCES Products(Id)
);
END
GO
-- Индексы для внешних ключей (улучшают производительность JOIN'ов)
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_Products_CategoryId')
CREATE INDEX IX_Products_CategoryId ON Products(CategoryId);
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_Orders_CustomerId')
CREATE INDEX IX_Orders_CustomerId ON Orders(CustomerId);
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_OrderItems_OrderId')
CREATE INDEX IX_OrderItems_OrderId ON OrderItems(OrderId);
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_OrderItems_ProductId')
CREATE INDEX IX_OrderItems_ProductId ON OrderItems(ProductId);
GO

View File

@ -0,0 +1,42 @@
-- 03_insert_data.sql
-- Скрипт для вставки тестовых данных
USE [AdoNetShop];
GO
-- Очистка таблиц перед вставкой (опционально, для чистоты эксперимента)
-- Отключаем проверку внешних ключей
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable 'DELETE FROM ?'
EXEC sp_MSForEachTable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL'
-- Сброс identity
DBCC CHECKIDENT ('Categories', RESEED, 0);
DBCC CHECKIDENT ('Products', RESEED, 0);
DBCC CHECKIDENT ('Customers', RESEED, 0);
DBCC CHECKIDENT ('Orders', RESEED, 0);
DBCC CHECKIDENT ('OrderItems', RESEED, 0);
GO
-- Добавляем категории
INSERT INTO Categories (Name) VALUES
('Laptops'),
('Smartphones'),
('Accessories');
-- Добавляем товары
INSERT INTO Products (Name, Description, Price, StockQuantity, CategoryId) VALUES
('Laptop Dell XPS 15', 'High performance laptop', 1500.00, 10, 1),
('MacBook Pro 14', 'Apple laptop with M2 chip', 1999.99, 5, 1),
('iPhone 14 Pro', 'Latest Apple smartphone', 999.00, 20, 2),
('Samsung Galaxy S23', 'Flagship Android phone', 899.50, 15, 2),
('Wireless Mouse', 'Ergonomic wireless mouse', 25.00, 50, 3),
('USB-C Hub', 'Multi-port adapter', 45.00, 30, 3);
-- Добавляем клиентов
INSERT INTO Customers (Name, Email, Phone) VALUES
('Ivan Ivanov', 'ivan@example.com', '+1234567890'),
('Petr Petrov', 'petr@example.com', '+0987654321');
-- Заказы добавлять не будем, создадим их из кода, чтобы протестировать транзакции
GO

28
database/04_queries.sql Normal file
View File

@ -0,0 +1,28 @@
-- 04_queries.sql
-- Примеры запросов
USE [AdoNetShop];
GO
-- Получить все товары с названиями категорий
SELECT
p.Id,
p.Name,
p.Price,
p.StockQuantity,
c.Name AS CategoryName
FROM Products p
JOIN Categories c ON p.CategoryId = c.Id;
-- Получить все заказы клиента с деталями
SELECT
o.Id AS OrderId,
o.OrderDate,
o.TotalAmount,
p.Name AS ProductName,
oi.Quantity,
oi.Price
FROM Orders o
JOIN OrderItems oi ON o.Id = oi.OrderId
JOIN Products p ON oi.ProductId = p.Id
WHERE o.CustomerId = 1;

View File

@ -0,0 +1,38 @@
-- 05_procedures.sql
-- Создание хранимых процедур
USE [AdoNetShop];
GO
-- Процедура для получения товаров по категории
CREATE OR ALTER PROCEDURE GetProductsByCategory
@CategoryId INT
AS
BEGIN
SET NOCOUNT ON;
SELECT Id, Name, Description, Price, StockQuantity, CategoryId
FROM Products
WHERE CategoryId = @CategoryId;
END
GO
-- Процедура для безопасного обновления цены
CREATE OR ALTER PROCEDURE UpdateProductPrice
@ProductId INT,
@NewPrice DECIMAL(18,2)
AS
BEGIN
SET NOCOUNT ON;
IF @NewPrice <= 0
BEGIN
RAISERROR ('Цена должна быть больше нуля.', 16, 1);
RETURN;
END
UPDATE Products
SET Price = @NewPrice
WHERE Id = @ProductId;
END
GO

19
database/06_test.sql Normal file
View File

@ -0,0 +1,19 @@
-- 06_test.sql
-- Тестовый скрипт (выполнять вручную для проверки базы)
USE [AdoNetShop];
GO
SELECT * FROM Categories;
SELECT * FROM Products;
SELECT * FROM Customers;
-- Тест процедуры
EXEC GetProductsByCategory @CategoryId = 1;
-- Тест обновления цены (успешный)
EXEC UpdateProductPrice @ProductId = 1, @NewPrice = 1450.00;
SELECT * FROM Products WHERE Id = 1;
-- Тест обновления цены (ошибка)
-- EXEC UpdateProductPrice @ProductId = 1, @NewPrice = -10.00;