2

LINQ to SQL を使用してレコードを選択しています。2 つのクエリを結合する必要がありますが、選択ステートメントが変更されているため、式が一致しなくなり、結合が妨げられています。

この LINQ クエリは、強制列 'resultType' と 'imageFile' を最終結果から除外します。

var taglist = from t in dc.ProductTags
 where t.Tag.StartsWith(prefixText)
 select new AutoSearch { 
      resultType = "Tag", 
      name = t.Tag, 
      imageFile = string.Empty, 
      urlElement = t.Tag };

これが提示されたクエリです。

{SELECT [t0].[Tag] AS [name] FROM [dbo].[ProductTag] AS [t0] WHERE [t0].[Tag] LIKE @p0}

これは、最初のクエリと結合される 2 番目のクエリです。

var brandlist = from b in dc.Businesses
                    join t in dc.Tags on b.BusinessId equals t.BusinessId
                    where b.Name.StartsWith(prefixText)
                    where b.IsActive == true
                    where t.IsActive == true
                        select new AutoSearch
                        { 
                        resultType = "Business", 
                        name = b.Name, 
                        imageFile = t.AdImage, 
                        urlElement = b.BusinessId.ToString() };

これは、2 番目のクエリの sql です。

SELECT [t0].[Name] AS [name], [t1].[AdImage] AS [imageFile], CONVERT(NVarChar(MAX) [t0].[BusinessId]) AS [urlElement] FROM [dbo].[Business] AS [t0] INNER JOIN [dbo].[Tag] AS [t1] ON ([t0].[BusinessId]) = [t1].[BusinessId] WHERE ([t0].[Name] LIKE @p0)

ユニオン...エラーをスローします。

var unionedResults = taglist.Union(brandlist);

スローされたエラー。

UNION、INTERSECT、または EXCEPT 演算子を使用して結合されたすべてのクエリでは、ターゲット リストに同じ数の式が含まれている必要があります。

これは AutoSearch クラスです。

    public class AutoSearch
    {
    public string name { get; set; }
    public string imageFile { get; set; }
    public string resultType { get; set; }
    public string urlElement { get; set; }
    }

何が起こっているかについての提案???

アップデート***

回避策を見つけました...

問題が見つかりました。

これは LINQ の既知のバグです。 SO に関するいくつかの議論がここで見つかり、正しい方向を示してくれました。サイトにリストされている回避策のほとんどは、 のバージョン 4.0 で壊れたため、もはや有効ではありません。私は働いた別のものを見つけました..

LINQ は、最適化のために重複する値を省略します。破棄フィールドの値を文字列または小文字に変換するか、連結することで変更できました。

ひどく非効率ですが、うまくいきます。これで一日が失われました。おそらく、他の人の時間を節約できます。

            var taglist = from t in dc.ProductTags
                      where t.Tag.StartsWith(prefixText)
                      let resultType = "Tag"
                      select new AutoSearch() {
                          resultType = resultType, 
                          name = t.Tag,
                          imageFile = t.Tag.ToString(),
                          urlElement = t.Tag.ToLower()
                      };

        var brandlist = from b in dc.Businesses
                    join t in dc.Tags on b.BusinessId equals t.BusinessId
                    where b.Name.StartsWith(prefixText)
                    where b.IsActive == true
                        where t.IsActive == true
                        where t.AdImage != null
                        where t.AdImage != String.Empty
                        let resultType = "Business"
                        select new AutoSearch
                        {
                            resultType = resultType, 
                            name = b.Name, 
                            imageFile = t.AdImage, 
                            urlElement = b.BusinessId.ToString()
                        };
4

1 に答える 1

1

クエリの選択部分を実行するときに参照する唯一のプロパティは Tag です。Linq to Sql はこれを認識し、参照している列のみを選択するようにクエリを最適化します。

つまり、クエリのこのセクションは、データベースのタグ列に関連付けられている「タグ」プロパティのみを参照します。

new AutoSearch { 
  resultType = "Tag", 
  name = t.Tag, 
  imageFile = string.Empty, 
  urlElement = t.Tag };

この場合、Linq が行うことは、基になるプロバイダーに式を渡すことです (バイナリ ツリー データ構造に非常に似ています)。その後、プロバイダーはこのツリーを解析し、実行時にそこから SQL クエリを作成します。最適化は実行時にプロバイダーによって行われ、表示されている SQL クエリが生成されます。

アップデート

ユニオンの 2 番目の問題については、基本的に、ユニオン エラーの原因となっている 2 つの異なる SQL ステートメントをユニオンしようとしています。それでは見てみましょう。

エラーの原因となる結果のステートメントは、次のようになります

SELECT [t0].[Tag] AS [name] FROM [dbo].[ProductTag] AS [t0] WHERE [t0].[Tag] LIKE @p0
UNION
SELECT [t0].[Name] AS [name], [t1].[AdImage] AS [imageFile], CONVERT(NVarChar(MAX) [t0].[BusinessId]) AS [urlElement] FROM [dbo].[Business] AS [t0] INNER JOIN [dbo].[Tag] AS [t1] ON ([t0].[BusinessId]) = [t1].[BusinessId] WHERE ([t0].[Name] LIKE @p0)

2 つの列の間に同じ数の列がなく、SQL ではうまくいかないため、明らかにこれは問題です。私は純粋な linq ソリューションを持っていませんが、回避策があります。

最初 に、送信された文字列を返すだけの SQL 関数を作成する必要があります。

CREATE FUNCTION ReturnString( @string varchar(max) )
RETURNS varchar(max)
AS
BEGIN
    RETURN @string
END
GO

次に、この新しい SQL 関数を dbml ファイルにドラッグ アンド ドロップし、最後にクエリで適切なメソッドを呼び出すだけです。

var taglist = from t in dc.ProductTags
                where t.Tag.StartsWith(prefixText)
                select new AutoSearch
                {
                    resultType = dc.ReturnString("Tag"),
                    name = t.Tag,
                    imageFile = dc.ReturnString(string.Empty),
                    urlElement = dc.ReturnString(t.Tag)
                };

var brandlist = from b in dc.Businesses
                join t in dc.Tags on b.BusinessId equals t.BusinessId
                where b.Name.StartsWith(prefixText)
                where b.IsActive == true
                where t.IsActive == true
                select new AutoSearch
                {
                    resultType = dc.ReturnString("Business"),
                    name = b.Name,
                    imageFile = t.AdImage,
                    urlElement = b.BusinessId.ToString()
                };

これでユニオンを実行できるはずです。

于 2013-08-14T21:48:20.080 に答える