Пример простого запроса для чтения данных с соединением двух таблиц:
return (from f in _context.Firms
join cr in _context.CatalogRubrics on f.RubricId equals cr.RubricId
where cr.UrlMask == rubric
&& f.IsAllowed
orderby f.Rank descending
select f).Take(N).AsNoTracking().ToList();
Соединние таблиц выполняется аналогично SQL: join cr in _context.CatalogRubrics on f.RubricId equals cr.RubricId. Первые N строк выбираются оператором Take(N) (в SQL это top(N)). AsNoTracking() указывает, что для запроса для чтения данных надо отключить отслеживание изменений.
select f - вернет данные только из одной таблицы f. Чтобы вернуть необходимые данные из обеих таблиц, надо сделать класс, который совмещает данные из этих таблиц, или, анонимно new { f, cr }.
📘 Сложные операторы запросов
◻ Запросы в Entity Framework Core (entityframeworktutorial.net)
◻ Linq-to-Entities Query (entityframeworktutorial.net)
Пример запроса, когда используются несколько полей и создается объект заданного типа:
SELECT City, UrlMask, ISO2
FROM CatalogRubricCities
GROUP BY City, UrlMask, ISO2
private IQueryable<City> RubricCityQuery()
{
return _context.CatalogRubricCities
.GroupBy(o => new { o.City, o.UrlMask, o.Iso2})
.Select(g => new City {Name = g.Key.City, UrlMask = g.Key.UrlMask, CountryCode = g.Key.Iso2});
}
//где то в программе вызов, например такой:
cities = await RubricCityQuery().AsNoTracking().ToListAsync();
📘 Преобразование оператора LINQ GroupBy
📘 Сложные операторы запросов: GroupBy
◻ Grouping and Aggregating Data with LINQ
📘 Группировка элементов последовательности
Еще вариант группировки с условием, подсчетом общего количества в группе и сортировкой по имени
public IList<City> GetFirmCities(List<OfficeCard> offices, out bool hasMore)
{
hasMore = (from o in offices where o.CityId == null select o).FirstOrDefault() != null;
return (from o in offices
where o.CityId != null
group o by (o.City, o.CityId) into g
select new City { Name = g.Key.City, Id = (int)g.Key.CityId, Count=g.Count() })
.OrderBy(g => g.Name).ToList();
//Другой вариант:
//return offices
// .Where(o=> o.CityId != null)
// .GroupBy(o => new { o.City, o.CityId})
// .Select(g => new City {Name = g.Key.City, Id =(int)g.Key.CityId})
// .OrderBy(g => g.Name)
// .ToList();
}
Когда есть основная таблица, а для некоторых записей есть сведения в связанной таблице. Но нам нужны данные для основной таблицы, даже если нет уточнений. Для этого в SQL используется оператор LEFT OUTER JOIN (левое соединение), который берет все данные из основной таблицы.
Можно использовать into:
SELECT f.*,fe.*
FROM Firms AS f LEFT OUTER JOIN
TFirmExtensions AS fe ON f.FirmId = fe.FirmId
var q= from f in _context.Firms
join fe in _context.TfirmExtensions on f.FirmId equals fe.FirmId
into Details
from d in Details.DefaultIfEmpty()
select new { f, d};
📘 Левое соединение
◻ EntityFramework: левое (внешнее) соединение в Linq (stackoverflow.com)
📘 Селектор коллекции ссылается на внешний источник в предложении WHERE
📘 Выполнение левых внешних соединений