ユニオンサポートの共通データ構造を使用して、ユーザーに最新の更新表示を提供するために、いくつかのクエリをまとめようとしています。私の最初の関数には、次のselect句があります。
.Select(x => new PlayerUpdateInfo
{
FirstName = x.PodOptimizedSearch.FirstName,
LastName = x.PodOptimizedSearch.LastName,
RecruitId = x.RecruitId,
Date = x.Date,
UpdateMessage = x.IsAddedAction
? "Player was added to this recruiting board by " + x.Person.FirstName
+ " " + x.Person.LastName
: "Player was removed from this recruiting board by " +
x.Person.FirstName + " " + x.Person.LastName,
// Defaults for union support
Team = string.Empty,
UpdateComments = x.Comments,
TeamId = 0,
State = string.Empty
});
これを呼び出すと、9つのフィールドを返すクエリが正しく生成されます。2番目の方法の選択は次のとおりです。
select new PlayerUpdateInfo
{
FirstName = recruit.FirstName,
LastName = recruit.LastName,
RecruitId = recruit.RecruitId,
Date = asset.CreateDate,
UpdateMessage = "New Full Game Added",
// Defaults for union support
Team = null,
UpdateComments = null,
TeamId = 0,
State = null
};
このクエリを単独で実行すると、9つの値が正しく返されます。しかし、私がやろうとすると
var query = GetFirstQuery();
query = query.union(GetSecondQuery());
すべてのクエリに同じ数のフィールドがないため、クエリが失敗したというSQL例外が発生します。生成されたSQLを調査すると、最初のクエリは正しいことがわかりますが、Linqは7つのフィールドのみを持つ2番目の(結合された)クエリを生成しています。テスト後、Linqはnullを「最適化」しているように見えるため、3つではなく1つのnull列のみが返されるため、不一致が発生します。
Linq-to-sqlが誤ってユニオンを生成するのはなぜですか?これを回避するにはどうすればよいですか?
編集:
この問題は、Linq-to-Sql for.Net3.5のユニオンチェーンを扱っているようです。これは明らかに4では起こりません。次のコードで:
protected IQueryable<PlayerUpdateInfo> Test1()
{
return PodDataContext.Assets
.Select(x => new PlayerUpdateInfo
{
Date = DateTime.Now,
FirstName = x.Title,
LastName = string.Empty,
RecruitId = 0,
State = string.Empty,
Team = string.Empty,
TeamId = 0,
UpdateComments = string.Empty,
UpdateMessage = string.Empty
});
}
protected IQueryable<PlayerUpdateInfo> Test2()
{
return PodDataContext.SportPositions
.Select(x => new PlayerUpdateInfo
{
Date = DateTime.Now,
FirstName = string.Empty,
LastName = x.Abbreviation,
RecruitId = 0,
State = string.Empty,
Team = string.Empty,
TeamId = 0,
UpdateComments = string.Empty,
UpdateMessage = string.Empty
});
}
次に、次の方法でチェーンを結合します。 var q2 = Test1().Union(Test2()).Union(Test1());
.Net 3.5では、次のSQLが取得されますが、これは不一致で失敗します
SELECT [t4].[value] AS [RecruitId], [t4].[Title] AS [FirstName], [t4].[value2] AS [LastName], [t4].[value22] AS [Team], [t4].[value3] AS [Date]
FROM (
SELECT [t2].[value], [t2].[Title], [t2].[value2], [t2].[value2] AS [value22], [t2].[value3]
FROM (
SELECT @p0 AS [value], [t0].[Title], @p1 AS [value2], @p2 AS [value3]
FROM [dbo].[Assets] AS [t0]
UNION
SELECT @p3 AS [value], @p4 AS [value2], [t1].[Abbreviation], @p5 AS [value3]
FROM [dbo].[SportPositions] AS [t1]
) AS [t2]
UNION
SELECT @p6 AS [value], [t3].[Title], @p7 AS [value2], @p8 AS [value3]
FROM [dbo].[Assets] AS [t3]
) AS [t4]
.net 4では、次のコードが生成されます。
SELECT [t4].[value] AS [RecruitId], [t4].[Title] AS [FirstName], [t4].[value2] AS [LastName], [t4].[value3] AS [Team], [t4].[value4] AS [TeamId], [t4].[value5] AS [State], [t4].[value6] AS [UpdateMessage], [t4].[value7] AS [UpdateComments], [t4].[value8] AS [Date]
FROM (
SELECT [t2].[value], [t2].[Title], [t2].[value2], [t2].[value3], [t2].[value4], [t2].[value5], [t2].[value6], [t2].[value7], [t2].[value8]
FROM (
SELECT @p0 AS [value], [t0].[Title], @p1 AS [value2], @p2 AS [value3], @p3 AS [value4], @p4 AS [value5], @p5 AS [value6], @p6 AS [value7], @p7 AS [value8]
FROM [dbo].[Assets] AS [t0]
UNION
SELECT @p8 AS [value], @p9 AS [value2], [t1].[Abbreviation], @p10 AS [value3], @p11 AS [value4], @p12 AS [value5], @p13 AS [value6], @p14 AS [value7], @p15 AS [value8]
FROM [dbo].[SportPositions] AS [t1]
) AS [t2]
UNION
SELECT @p16 AS [value], [t3].[Title], @p17 AS [value2], @p18 AS [value3], @p19 AS [value4], @p20 AS [value5], @p21 AS [value6], @p22 AS [value7], @p23 AS [value8]
FROM [dbo].[Assets] AS [t3]
) AS [t4]
これは有効なSQLであり、機能します。さまざまな理由で本番システムを.net4に移行できないため、.net 3.5でこれを回避する方法を知っている人はいますか?