1

次に例を示します。

国、人、都市の3つのテーブルがあるとします。都市レコードには、国を識別するnull不可の外部キーフィールドがあります。人のレコードには、国を識別するnull許容の外部キーフィールドがあります。これらは、もはや存在しない東ヨーロッパの国からのものである可能性があります。

人々のリストと都市のリストから国の組み合わせリストを作成したいと思います。

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は(正しく)すべての国のない人に対してnullで満たされた行があることを確認するクエリを作成しています。デバッガーでは、これは「[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は、これによってnull行が防止されることを認識しないため、テスト列を挿入します。テスト列は表示されないため、IQueryableオブジェクトとして報告されているものからテスト列を「削除」する明確な方法はありません。最終的な結果は、列の数が等しくないUNIONコンストラクトに関する実行時エラーです。

null許容型の関係でINNERJOINを強制する方法、または非表示のテスト列を除外してユニオンを希望どおりに機能させるにはどうすればよいですか?

4

1 に答える 1

1

マッピングでリレーションシップを使用するのが理想的ですが、これは適切な回避策になる可能性があります。

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));
于 2009-09-01T17:08:41.023 に答える