Разница между интерфейсом IQueryable, ICollection, IList и IDictionary
Я пытаюсь понять разницу между интерфейсами IQueryable, ICollection, IList и IDictionary
который быстрее работает для основных операций, таких как итерация, индексирование, запрос и многое другое.
какой класс, например Collection, List, Dictionary и т.д., был бы хорош для инициализации с помощью этих интерфейсов и когда мы должны использовать этот класс. Основные преимущества использования этих классов над другими.
Я пробовал читать другие сообщения с похожими вопросами, но ничего не ответил на мои полные вопросы.
Спасибо за помощь.
Ответы
Ответ 1
Все эти интерфейсы наследуются от IEnumerable, которые вы должны убедиться, что понимаете. Этот интерфейс в основном позволяет использовать класс в инструкции foreach
(на С#).
- ICollection - это самый простой из перечисленных вами интерфейсов. Это перечислимый интерфейс, который поддерживает граф и что об этом.
- IList - это все, что есть ICollection, но оно также поддерживает добавление и удаление элементов, извлечение элементов по индексу и т.д. Это наиболее часто используемый интерфейс для "списков объектов", который является неопределенным Я знаю.
- IQueryable - это перечислимый интерфейс, поддерживающий LINQ. Вы всегда можете создать IQueryable из IList и использовать LINQ to Objects, но вы также обнаружите, что IQueryable используется для отложенного выполнения операторов SQL в LINQ to SQL и LINQ to Entities.
- IDictionary - это другое животное в том смысле, что оно является отображением уникальных ключей к значениям. Это также перечислимо тем, что вы можете перечислить пары ключ/значение, но в противном случае оно служит другой цели, чем другие, которые вы указали.
Документация MSDN для каждого из них является достойной, поэтому я бы начал там, округляя ваше понимание.
Ответ 2
IQueryable, IList, IDictionary, ICollection наследует IEnumerable Interface.
Все интерфейсы коллекции типов наследуют IEnumerable Interface.
Различия между IEnumerable и IQueryable
IEnumerable: - при запуске запроса, который возвращает тип IEnumerable.
Сначала IEnumerable Выполняет первый запрос, а затем выполняет вспомогательные запросы, написанные для этого запроса.
Пример: - Если вы хотите получить 10 записей населения из конкретной страны, то запрос, который мы будем использовать в LinQ,
IEnumerable _Population = from s в Индии выберите s.population;//Первый запрос
_Population = _Population.take(10);//Второй запрос
Теперь, если мы выполним этот запрос, первый запрос будет выполнен первым, IEnumerable получит записи всей совокупности из SQL-сервера, тогда он сохранит данные в памяти In Process, а затем выполнит первую десятку пользователей в следующий запрос. (Выполнение выполняется два раза на сервере sql).
если мы выполним тот же запрос, используя IQueryable.
IQueryable _Population = from s в Индии выберите s.population;//Первый запрос
_Population = _Population.take(10);//Второй запрос
в этом IQueryable он будет выполнять два Запроса одновременно, в том смысле, что он получит население, которое входит в первую десятку в одном запросе, вместо того, чтобы получать данные и фильтровать первые 10 снова. (Однократное выполнение на sql server).
Заключение для IQueryable и IEnumerable
- Если вы пишете запрос с данными в базе данных, тогда
используйте IQueryable.
- Если вы запрашиваете данные процесса, тогда
используйте IEnumerable.
IEnumerable имеет методы GetEnumerator(), Current() и MoveNext().
Ответ 3
Я заметил несколько вопросов в ответе @gunny229 выше, поэтому я пишу этот пост. Я упомянул эти проблемы и в области комментариев его должности. Чтобы исправить этот пост, мне пришлось бы переписать почти всю запись, поэтому я подумал о создании своего. Я не намерен полностью обрабатывать вопрос OP, но я хочу указать разницу между IQueryable и IEnumerable при использовании LINQ to SQL.
Я создал следующую структуру в БД (DDL script):
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
Вот вставка записи script (DML script):
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
Теперь моя цель состояла в том, чтобы просто получить лучшие 2 записи из таблицы Employee
в базе данных. Итак, я добавил элемент модели данных Entity Data ADO.NET в мое консольное приложение, указав на таблицу Employee
в моей базе данных и начал писать запросы LINQ.
Код для маршрута IQueryable:
using (var efContext = new EfTestEntities())
{
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Когда я начал запускать эту программу, я также начал сеанс профилирования SQL Query на моем экземпляре SQL Server и вот сводка о выполнении:
- Общее количество запущенных запросов: 1
- Текст запроса:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
Просто IQueryable
достаточно умен, чтобы применить предложение Top (2)
на стороне сервера базы данных, поэтому он выводит только 2 из 5 записей по проводу. Любая дополнительная фильтрация в памяти не требуется вообще на стороне клиентского компьютера.
Код для маршрута IEnumerable:
using (var efContext = new EfTestEntities())
{
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Сводка выполнения в этом случае:
- Общее количество запущенных запросов: 1
- Текст запроса, захваченный в профилировщике SQL:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
Теперь вещь IEnumerable
привела все 5 записей, присутствующих в таблице Salary
, а затем выполнила фильтрацию в памяти на клиентском компьютере, чтобы получить первые 2 записи. Таким образом, больше данных (3 дополнительных записи в этом случае) было передано по проводам без необходимости.