2

我正在使用 LINQ to SQL 来选择记录。我需要将两个查询合并在一起,但是选择语句正在更改,因此表达式不再匹配,从而阻止了合并。

此 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}

这是要与初始查询联合的第二个查询。

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() };

这是第二个查询的 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 运算符组合的所有查询必须在其目标列表中具有相同数量的表达式。

这是自动搜索类。

    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 知道这一点并优化查询以仅选择您引用的列。

换句话说,您查询的这一部分仅引用“Tag”属性,该属性与数据库中的 Tag 列相关联。

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

在这种情况下,Linq 所做的是将表达式传递给底层提供程序(非常类似于二叉树数据结构)。然后,提供者解析这棵树并在运行时从它创建一个 SQL 查询。优化由提供程序在运行时完成,这会导致您看到的 SQL 查询。

更新

对于联合的第二个问题,您基本上是在尝试联合两个导致联合错误的不同 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)

显然这是有问题的,因为两者之间的列数不一样,而且 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 回答