🤔 Пример выполнения кода, когда возвращается объект интерфейса Iqueryable?
🚩Пример работы с `IQueryable<T>` на Entity Framework Core
Предположим, у нас есть сущность
Теперь создадим репозиторий, который возвращает
🚩Вызов метода и выполнение запроса
Запрос к базе данных выполнится только при материализации (
Ставь 👍 и забирай 📚 Базу знаний
IQueryable<T> — это интерфейс, который используется для отложенного выполнения запросов (deferred execution). Он позволяет строить SQL-запросы к базе данных или манипулировать данными в памяти, но сам запрос выполняется только в момент его итерации (ToList(), FirstOrDefault(), Count(), и т. д.).🚩Пример работы с `IQueryable<T>` на Entity Framework Core
Предположим, у нас есть сущность
Product и контекст базы данных AppDbContextpublic class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("YourConnectionString");
}
}
Теперь создадим репозиторий, который возвращает
IQueryable<Product>public class ProductRepository
{
private readonly AppDbContext _context;
public ProductRepository(AppDbContext context)
{
_context = context;
}
public IQueryable<Product> GetProducts()
{
return _context.Products.Where(p => p.Price > 100);
// Запрос не выполняется здесь! Только формируется
}
}
🚩Вызов метода и выполнение запроса
Запрос к базе данных выполнится только при материализации (
ToList(), FirstOrDefault(), Count(), и т. д.).var repository = new ProductRepository(new AppDbContext());
// Создаём IQueryable-запрос
IQueryable<Product> query = repository.GetProducts();
// Добавляем дополнительное условие (запрос еще НЕ выполнен)
query = query.OrderBy(p => p.Name);
// Теперь выполняем запрос к БД
List<Product> products = query.ToList(); // SQL-запрос отправляется в базу
Ставь 👍 и забирай 📚 Базу знаний
🤔 Как оптимизировать ситуацию, когда к таблице много join?
1. Проверить необходимость всех join — убрать ненужные связи.
2. Использовать индексы — создать индексы на ключевых колонках.
3. Разделить запрос — разбить сложный запрос на несколько более простых.
4. Использовать denormalization — объединить часто используемые данные в одну таблицу.
5. Кэшировать данные — уменьшить нагрузку на базу данных.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
1. Проверить необходимость всех join — убрать ненужные связи.
2. Использовать индексы — создать индексы на ключевых колонках.
3. Разделить запрос — разбить сложный запрос на несколько более простых.
4. Использовать denormalization — объединить часто используемые данные в одну таблицу.
5. Кэшировать данные — уменьшить нагрузку на базу данных.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🤔 Можно ли передать строку в lock?
Можно, но не рекомендуется. Строки могут быть разделяемыми между разными частями программы, даже если они написаны одинаково. Это может привести к неожиданным блокировкам. Лучше использовать уникальные объекты, специально созданные для блокировки.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Можно, но не рекомендуется. Строки могут быть разделяемыми между разными частями программы, даже если они написаны одинаково. Это может привести к неожиданным блокировкам. Лучше использовать уникальные объекты, специально созданные для блокировки.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🔥2
🤔 Какая разница между private и protected методами?
- private — доступен только внутри текущего класса.
- protected — доступен внутри текущего класса и его наследников.
private обеспечивает максимальную инкапсуляцию, а protected позволяет наследникам переопределять поведение или использовать базовые методы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- private — доступен только внутри текущего класса.
- protected — доступен внутри текущего класса и его наследников.
private обеспечивает максимальную инкапсуляцию, а protected позволяет наследникам переопределять поведение или использовать базовые методы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🤔 Что такое unsafe?
Используется для объявления небезопасного контекста кода, который позволяет выполнять низкоуровневые операции, такие как манипуляции с указателями. Эти операции обычно не разрешены в безопасном управляемом коде, но могут быть необходимы для взаимодействия с неуправляемым кодом, оптимизации производительности или доступа к определенным системным ресурсам.
🚩Характеристики
🟠Объявление небезопасного контекста
Чтобы использовать указатели и выполнять небезопасные операции, нужно объявить метод, блок кода или тип как
🟠Компиляция с поддержкой `unsafe`
Для компиляции кода с
1⃣Откройте свойства проекта.
2⃣Перейдите на вкладку "Сборка".
3⃣Установите флажок "Разрешить небезопасный код".
🟠Использование указателей
Указатели позволяют напрямую работать с адресами памяти, что может быть полезно для некоторых оптимизаций или взаимодействия с низкоуровневым кодом, написанным на C или C++.
🟠Небезопасные структуры
Вы можете объявлять структуры с указателями и использовать их в небезопасном контексте.
🟠Стековые указатели (stackalloc)
🟠Взаимодействие с неуправляемым кодом
Небезопасный код часто используется для взаимодействия с API, написанными на других языках, такими как C или C++.
🚩Плюсы
➕Производительность
Позволяет выполнять высокоэффективные операции с памятью.
➕Взаимодействие с неуправляемым кодом
Необходим для вызова функций из библиотек, написанных на других языках.
➕Низкоуровневый контроль
Предоставляет возможность прямого управления памятью и аппаратными ресурсами.
Ставь 👍 и забирай 📚 Базу знаний
Используется для объявления небезопасного контекста кода, который позволяет выполнять низкоуровневые операции, такие как манипуляции с указателями. Эти операции обычно не разрешены в безопасном управляемом коде, но могут быть необходимы для взаимодействия с неуправляемым кодом, оптимизации производительности или доступа к определенным системным ресурсам.
🚩Характеристики
🟠Объявление небезопасного контекста
Чтобы использовать указатели и выполнять небезопасные операции, нужно объявить метод, блок кода или тип как
unsafe. unsafe void UnsafeMethod()
{
int a = 10;
int* p = &a; // Использование указателя
Console.WriteLine(*p); // Разыменование указателя
}
🟠Компиляция с поддержкой `unsafe`
Для компиляции кода с
unsafe необходимо включить поддержку небезопасного кода в настройках проекта. В Visual Studio это делается через свойства проекта:1⃣Откройте свойства проекта.
2⃣Перейдите на вкладку "Сборка".
3⃣Установите флажок "Разрешить небезопасный код".
🟠Использование указателей
Указатели позволяют напрямую работать с адресами памяти, что может быть полезно для некоторых оптимизаций или взаимодействия с низкоуровневым кодом, написанным на C или C++.
unsafe void PointerExample()
{
int a = 5;
int* p = &a; // p указывает на адрес переменной a
Console.WriteLine((int)p); // Вывод адреса переменной a
Console.WriteLine(*p); // Вывод значения переменной a через указатель
}
🟠Небезопасные структуры
Вы можете объявлять структуры с указателями и использовать их в небезопасном контексте.
unsafe struct UnsafeStruct
{
public int* Pointer;
}
🟠Стековые указатели (stackalloc)
stackalloc позволяет выделять память в стеке для массива в небезопасном контексте. Это может быть быстрее, чем выделение памяти в куче. unsafe void StackAllocExample()
{
int* array = stackalloc int[10]; // Выделение массива из 10 целых чисел в стеке
for (int i = 0; i < 10; i++)
{
array[i] = i;
}
}
🟠Взаимодействие с неуправляемым кодом
Небезопасный код часто используется для взаимодействия с API, написанными на других языках, такими как C или C++.
[DllImport("user32.dll")]
extern static unsafe int MessageBox(IntPtr hWnd, char* text, char* caption, int options);
unsafe void CallUnmanagedCode()
{
char* text = "Hello, World!";
char* caption = "My Message Box";
MessageBox(IntPtr.Zero, text, caption, 0);
}🚩Плюсы
➕Производительность
Позволяет выполнять высокоэффективные операции с памятью.
➕Взаимодействие с неуправляемым кодом
Необходим для вызова функций из библиотек, написанных на других языках.
➕Низкоуровневый контроль
Предоставляет возможность прямого управления памятью и аппаратными ресурсами.
Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 Что такое предикат?
Это делегат, представляющий метод, который принимает один или несколько аргументов и возвращает логическое значение (
🚩Особенности
🟠Тип делегата
В C# предикат представлен делегатом
🟠Использование
Предикаты обычно используются в методах стандартных коллекций, таких как
🚩Пример использования предиката
Определение предиката
Использование предиката с методом коллекции
🚩Лямбда-выражения как предикаты
Лямбда-выражения часто используются для определения предикатов непосредственно в месте вызова метода. Это делает код более компактным и удобочитаемым.
Пример использования лямбда-выражений
🚩Сценарии использования предикатов
🟠Фильтрация коллекций
Предикаты используются для определения условий фильтрации элементов в коллекциях.
🟠Поиск элементов
Предикаты помогают находить элементы, соответствующие определенному условию.
🟠Удаление элементов
Предикаты используются для удаления элементов, соответствующих определенному условию.
Ставь 👍 и забирай 📚 Базу знаний
Это делегат, представляющий метод, который принимает один или несколько аргументов и возвращает логическое значение (
true или false). Предикаты часто используются для фильтрации коллекций, поиска элементов и других операций, связанных с условными проверками.🚩Особенности
🟠Тип делегата
В C# предикат представлен делегатом
Predicate<T>, который принимает один аргумент типа T и возвращает bool.🟠Использование
Предикаты обычно используются в методах стандартных коллекций, таких как
List<T>, для поиска, удаления и фильтрации элементов.🚩Пример использования предиката
Определение предиката
public static bool IsEven(int number)
{
return number % 2 == 0;
}
Использование предиката с методом коллекции
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
// Использование предиката для поиска первого четного числа
int firstEven = numbers.Find(IsEven);
Console.WriteLine("First even number: " + firstEven);
// Использование предиката для удаления всех четных чисел
numbers.RemoveAll(IsEven);
Console.WriteLine("Numbers after removing evens: " + string.Join(", ", numbers));
}
public static bool IsEven(int number)
{
return number % 2 == 0;
}
}
🚩Лямбда-выражения как предикаты
Лямбда-выражения часто используются для определения предикатов непосредственно в месте вызова метода. Это делает код более компактным и удобочитаемым.
Пример использования лямбда-выражений
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
// Использование лямбда-выражения для поиска первого четного числа
int firstEven = numbers.Find(n => n % 2 == 0);
Console.WriteLine("First even number: " + firstEven);
// Использование лямбда-выражения для удаления всех четных чисел
numbers.RemoveAll(n => n % 2 == 0);
Console.WriteLine("Numbers after removing evens: " + string.Join(", ", numbers));
}
}
🚩Сценарии использования предикатов
🟠Фильтрация коллекций
Предикаты используются для определения условий фильтрации элементов в коллекциях.
List<int> evenNumbers = numbers.FindAll(IsEven);
🟠Поиск элементов
Предикаты помогают находить элементы, соответствующие определенному условию.
int firstEven = numbers.Find(IsEven);
🟠Удаление элементов
Предикаты используются для удаления элементов, соответствующих определенному условию.
numbers.RemoveAll(IsEven);
Ставь 👍 и забирай 📚 Базу знаний
🤔 Чем отличается IQueryable от IEnumerable?
`IEnumerable` используется для перебора коллекции в памяти и поддерживает ленивую загрузку данных. `IQueryable` позволяет работать с данными на уровне источника данных, поддерживая отложенное выполнение запросов и возможность составления SQL-запросов для баз данных. `IQueryable` чаще используется в LINQ для работы с базами данных, а `IEnumerable` — для работы с коллекциями, уже загруженными в память. `IQueryable` может оптимизировать запросы, выполняя их на сервере базы данных.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍1🔥1
🤔 Что такое куки и где оно хранится в запросе?
Это небольшие фрагменты данных, которые веб-сайты сохраняют на устройствах пользователей для хранения информации о сессии и отслеживания состояния. Куки используются для различных целей, таких как аутентификация пользователей, хранение настроек и предпочтений, а также отслеживание активности пользователей на сайте.
🚩Основные свойства
🟠Имя (Name)
Уникальный идентификатор для каждого куки.
🟠Значение (Value)
Данные, которые хранит куки.
🟠Домен (Domain)
Домен, для которого куки действителен.
🟠Путь (Path)
Путь на сервере, для которого куки действителен.
🟠Время истечения (Expiration/Max-Age)
Дата или время, когда куки должен быть удален.
🟠Безопасность (Secure)
Указывает, что куки должны передаваться только через HTTPS.
🟠HTTPOnly
Указывает, что куки недоступен через JavaScript, только через HTTP(S) запросы.
🚩Где хранятся
🟠Установка куки с сервера (Set-Cookie)
Сервер отправляет куки в ответе на запрос клиента с использованием заголовка
🟠Отправка куки клиентом (Cookie)
Браузер автоматически добавляет соответствующие куки в заголовок
🚩Пример использования
Установка куки на сервере (пример на Node.js с использованием Express)
Доступ к куки на клиенте (пример на JavaScript)
🚩Важные моменты
🟠Безопасность
Куки с флагом
🟠Размер и количество
Обычно один куки не должен превышать 4KB, и на одном домене может быть установлено не более 20-30 куки.
🟠Конфиденциальность
Куки могут содержать чувствительные данные, поэтому важно защищать их и использовать шифрование, если необходимо.
Ставь 👍 и забирай 📚 Базу знаний
Это небольшие фрагменты данных, которые веб-сайты сохраняют на устройствах пользователей для хранения информации о сессии и отслеживания состояния. Куки используются для различных целей, таких как аутентификация пользователей, хранение настроек и предпочтений, а также отслеживание активности пользователей на сайте.
🚩Основные свойства
🟠Имя (Name)
Уникальный идентификатор для каждого куки.
🟠Значение (Value)
Данные, которые хранит куки.
🟠Домен (Domain)
Домен, для которого куки действителен.
🟠Путь (Path)
Путь на сервере, для которого куки действителен.
🟠Время истечения (Expiration/Max-Age)
Дата или время, когда куки должен быть удален.
🟠Безопасность (Secure)
Указывает, что куки должны передаваться только через HTTPS.
🟠HTTPOnly
Указывает, что куки недоступен через JavaScript, только через HTTP(S) запросы.
🚩Где хранятся
🟠Установка куки с сервера (Set-Cookie)
Сервер отправляет куки в ответе на запрос клиента с использованием заголовка
Set-Cookie. HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; Path=/; Expires=Wed, 09 Jun 2023 10:18:14 GMT
Content-Type: text/html
🟠Отправка куки клиентом (Cookie)
Браузер автоматически добавляет соответствующие куки в заголовок
Cookie при каждом последующем запросе к серверу, для которого эти куки действительны. GET /dashboard HTTP/1.1
Host: example.com
Cookie: sessionId=abc123
🚩Пример использования
Установка куки на сервере (пример на Node.js с использованием Express)
const express = require('express');
const app = express();
app.get('/', (req, res) => {
// Устанавливаем куки
res.cookie('sessionId', 'abc123', {
maxAge: 900000,
httpOnly: true
});
res.send('Куки установлены');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});Доступ к куки на клиенте (пример на JavaScript)
// Установка куки
document.cookie = "username=JohnDoe; expires=Thu, 18 Dec 2023 12:00:00 UTC; path=/";
// Получение всех куки
let cookies = document.cookie;
console.log(cookies);
🚩Важные моменты
🟠Безопасность
Куки с флагом
Secure передаются только по HTTPS-соединениям. Куки с флагом HttpOnly недоступны через JavaScript, что помогает защитить их от XSS-атак.🟠Размер и количество
Обычно один куки не должен превышать 4KB, и на одном домене может быть установлено не более 20-30 куки.
🟠Конфиденциальность
Куки могут содержать чувствительные данные, поэтому важно защищать их и использовать шифрование, если необходимо.
Ставь 👍 и забирай 📚 Базу знаний
🤔 Какие есть подходы в рамках EF Core?
Entity Framework Core предлагает несколько стратегий работы с зависимостями и контекстом:
- Scoped контекст — создаётся на время одного запроса.
- Transient контекст — создаётся каждый раз заново.
- Singleton — крайне редко используется, так как контекст не потокобезопасен.
Также в EF Core есть несколько подходов к маппингу и конфигурации:
- Fluent API (в OnModelCreating)
- Аннотации атрибутов ([Key], [Required] и др.)
- Разделение конфигураций на отдельные классы (EntityTypeConfiguration)
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Entity Framework Core предлагает несколько стратегий работы с зависимостями и контекстом:
- Scoped контекст — создаётся на время одного запроса.
- Transient контекст — создаётся каждый раз заново.
- Singleton — крайне редко используется, так как контекст не потокобезопасен.
Также в EF Core есть несколько подходов к маппингу и конфигурации:
- Fluent API (в OnModelCreating)
- Аннотации атрибутов ([Key], [Required] и др.)
- Разделение конфигураций на отдельные классы (EntityTypeConfiguration)
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🤔 Что такое делегаты и зачем они нужны?
Делегаты — это типы, которые безопасно инкапсулируют методы, подобно указателям на функции в других языках программирования, но с проверкой типов во время компиляции. Могут ссылаться на метод, который принимает параметры и возвращает значение. Они используются для реализации обратных вызовов и событий, а также для определения пользовательских операций, которые могут быть выполнены методом, принимаемым в качестве параметра.
🚩Зачем они нужны?
🟠Обратные вызовы (Callbacks)
Делегаты предоставляют механизм для передачи методов в качестве аргументов другим методам. Это полезно для реализации обратных вызовов, позволяя вызывать методы в ответ на определенные события или условия.
🟠События
Являются основой системы событий. Они позволяют определять события и подписываться на них. Когда событие происходит, вызываются делегаты, связанные с этим событием, что позволяет реагировать на изменения или действия пользователя.
🟠Параметризация методами
Позволяют создавать более гибкие и масштабируемые приложения, поскольку методы могут быть переданы и использованы динамически в различных контекстах.
🟠Асинхронное программирование
Используются для асинхронного программирования, позволяя выполнять задачи в фоновом режиме, не блокируя основной поток приложения.
Ставь 👍 и забирай 📚 Базу знаний
Делегаты — это типы, которые безопасно инкапсулируют методы, подобно указателям на функции в других языках программирования, но с проверкой типов во время компиляции. Могут ссылаться на метод, который принимает параметры и возвращает значение. Они используются для реализации обратных вызовов и событий, а также для определения пользовательских операций, которые могут быть выполнены методом, принимаемым в качестве параметра.
🚩Зачем они нужны?
🟠Обратные вызовы (Callbacks)
Делегаты предоставляют механизм для передачи методов в качестве аргументов другим методам. Это полезно для реализации обратных вызовов, позволяя вызывать методы в ответ на определенные события или условия.
🟠События
Являются основой системы событий. Они позволяют определять события и подписываться на них. Когда событие происходит, вызываются делегаты, связанные с этим событием, что позволяет реагировать на изменения или действия пользователя.
🟠Параметризация методами
Позволяют создавать более гибкие и масштабируемые приложения, поскольку методы могут быть переданы и использованы динамически в различных контекстах.
🟠Асинхронное программирование
Используются для асинхронного программирования, позволяя выполнять задачи в фоновом режиме, не блокируя основной поток приложения.
public delegate int Operation(int x, int y);
public class Calculator
{
public int PerformOperation(int x, int y, Operation op)
{
return op(x, y);
}
}
class Program
{
static int Add(int x, int y)
{
return x + y;
}
static int Multiply(int x, int y)
{
return x * y;
}
static void Main()
{
Calculator calc = new Calculator();
// Создание делегата для метода Add и вызов через метод PerformOperation
Operation addOp = new Operation(Add);
int result = calc.PerformOperation(5, 6, addOp);
Console.WriteLine("Addition: " + result);
// Создание делегата для метода Multiply и вызов через метод PerformOperation
Operation mulOp = new Operation(Multiply);
result = calc.PerformOperation(5, 6, mulOp);
Console.WriteLine("Multiplication: " + result);
}
}
Ставь 👍 и забирай 📚 Базу знаний