Linq и обнуляемые ключевые взаимосвязи, влияющие на работу UNION - PullRequest
1 голос
/ 01 сентября 2009

Вот пример:

Допустим, у меня есть 3 таблицы: страны, люди и города.Городские записи имеют необнуляемое поле внешнего ключа, идентифицирующее страну.В записях людей есть поле nullable внешнего ключа, идентифицирующее страну - они могут быть из восточноевропейской страны, которой больше нет.

Я хочу создать объединенный список стран из спискалюди и список городов:

var people = dbContext.People.Where(...);
var cities = dbContext.Cities.Where(...);

var countries = cities.Select(c=>c.Country);
countries = countries.Union(people.Select(p=>p.Country));

Проблема исходит из этой последней строки.Поскольку не все записи о людях имеют соответствующую запись о стране, LINQ (правильно) создает запрос, который гарантирует, что для каждого лица без гражданства будет строка, заполненная нулями.Похоже, что с помощью отладчика это делается путем создания пустого вызова столбца «[test]»

SELECT [t2].[test], [t2].[CountryID], [t2].[Name]
FROM [dbo].[People] AS [t0]
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[CountryID], [t1].[Name]
    FROM [dbo].[Countries] AS [t1]
    ) AS [t2] ON [t2].[CountryID] = [t0].[CountryID]

Пока этот дополнительный столбец [test] удаляется в коде (результат определяется как IQueryable) в кодеНа стороне SQL он определенно присутствует и приводит к отклонению запроса, когда я объединяю его с нормальным оператором выбора страны.

В последнем случае я не хочу или не нуждаюсь в дополнительномфиктивные строки - в полную программу, которую я уже включил people.Where(p=>p.CountryID != null).Select(p=>p.Country), а также попытку p=>Country != null.

Однако Linq не распознает, что это предотвратит пустые строки, и поэтому все еще вставляет тестовый столбец.так как тестовый столбец невидим, у меня нет очевидного способа «удалить» его из того, что иначе сообщается как объект IQueryable.Конечным результатом является ошибка во время выполнения из-за того, что моя конструкция UNION имеет неравное количество столбцов.

Как я могу принудительно включить INNER JOIN в моих связываемых отношениях или иным образом заставить объединение работать так, как я хочу, исключивневидимая тестовая колонка?

1 Ответ

1 голос
/ 01 сентября 2009

Я знаю, что в идеале вы должны использовать отношения в отображении, но это может быть хорошим обходным путем.

var people = dbContext.People.Where(...);
var cities = dbContext.Cities.Where(...);

var countryIds =
  cities
    .Select(c => c.CountryID)
  .Union(people
    .Select(p => p.CountryID)
    .Where(cID => cID.HasValue)
    .Select(cID => cID.Value));

var countries = dbContext.Countries
  .Where(c => countryIds.Contains(c.CountryID));
...