【问题标题】:Join Tables with Different DataType in Linq在 Linq 中连接具有不同数据类型的表
【发布时间】:2020-10-05 20:57:51
【问题描述】:

我有两个表需要将表 1 左外连接到表 2,但表 1 课程标题是 VARCHAR(1000),表 2 课程标题是文本数据类型。我对这两个字段都使用了 ToString() ,但仍然出现错误。以下是我的加入查询:

IQueryable<joinedTable> qry=(from a in db.table1
                join b in db.table2 on
                new {SUBJECT=a.SUBJECT, CATALOG_NBR=a.CATALOG_NBR, COURSETITLE=a.COURSETITLE.ToString() } equals
                new { SUBJECT = b.SUBJECT, CATALOG_NBR = b.CATALOG_NBR, COURSETITLE=b.COURSETITLE.ToString() } into ab
                from x  in ab.DefaultIfEmpty()
                select new joinedTable()
                {
                ID=a.ID,
                SUBJECT=a.SUBJECT,
                CATALOG_NBR=a.CATALOG_NBR,
                COURSETITLE=a.COURSETITLE,
                DESCR=x.DESCR
                }.AsQueryable();

错误:

“数据类型 varchar 和 text 在等于运算符中不兼容。”

【问题讨论】:

  • 它们在 C# 中是什么类型?
  • 两者都是公共字符串 COURSETITLE {get;设置;}
  • This answer 建议告诉 EF Core 3.1 它是 varchar,即使它是 text - 你使用的是什么 EF? PS由于C#数据类型是string,当然ToString什么都不做。

标签: c# linq linq-to-entities


【解决方案1】:

使用预选确保您要加入的键相等:

var preselectTable1 = db.Table1.Select(row => new
{
    JoinKey = new
    {
        Subject = row.SUBJECT,
        CatalogNbr = row.CATALOG_NBR,
        CourseTitle = row.COURSETITLE.ToString(),
    },

    ... // select the other table1 properties that you want to put in your final result
});

var preselectTable2 = db.Table2.Select(row => new
{
    JoinKey = new
    {
        Subject = row.SUBJECT,
        CatalogNbr = row.CATALOG_NBR,
        CourseTitle = row.COURSETITLE.ToString(),
    },

    ... // select the other table2 properties that you want to put in your final result
});

现在两个 JoinKey 是完全相同的类型。注意:还没有执行查询,没有联系数据库,只是调整了查询​​的表达式。

当您需要“客户及其订单”、“学校及其学生”、“表 1 中的行及其表 2 中的行”时,请考虑使用 overloads of GroupJoin 之一,而不是加入。我通常使用带有参数 resultSelector 的重载,所以我可以微调我的结果。

要获取 table1 行,每行都有零个或多个匹配 table2 行,请使用GroupJoin

var result = preselectTable1.GroupJoin(preselectTable2,

    table1Row => table1Row.JoinKey,    // from every row in table1 get the joinKey
    table2Row => table2Row.JoinKey,    // from every row in table2 get the joinKey

    // parameter result selector: from every row in table 1 and all rows in table2
    // that have the same value for JoinKey make one new:
    (table1Row, matchingTable2Rows) => new
    {
         // select the table1 properties that you want to use
         Id = table1Row.Id,
         Name = table1Row.Name,
         ...

         matching2Items = matchingTable2Rows.Select(table2Row  => new
         {
             // select the table2 properties that you want.
             Id = table2Row.Id,
             Name = table2Row.Name,
             ...
         })
         .ToList(),
    });

在上面的示例中,结果似乎有点奇怪。那是因为我不知道 table1 和 table2 是什么。如果您对“Customer and their Orders”执行同样的操作,结果看起来会非常自然:

IQueryable<Customer> customers = ...
IQueryable<Order> orders = ...

var customersWithTheirOrders = customers.GroupJoin(orders,

    customer => customer.Id,         // from each Customer take the primary key
    order => order.CustomerId,       // from each order take the foreign key

    (customer, ordersOfThisCustomer) => new
    {
        Id = customer.Id,

        AddressLabel = new AddressLabel
        {
            Name = customer.Name,
            Street = customer.Street,
            City = ...
        }

        Orders = ordersOfThisCustomer.Select(order => new
        {
             Id = order.Id,
             Date = order.Date,
             Total = order.Total,
             ...
        })
        .ToList(),
    });

除了获得“table1 项目及其匹配的 table2 项目”比“table1 项目与匹配的 table 2 项目”的组合序列感觉更自然之外,groupjoin 的优点之一是 item1属性只传输一次。

如果 School[10] 有 2000 名学生,则只传输一次 School[10] 的数据要比为每 2000 名学生传输一次相同的学校数据更有效。

如果你真的想要一个扁平的最终结果,请使用SelectMany.

【讨论】:

    【解决方案2】:
    IQueryable<joinedTable> qry = (from a in db.table1
                                               join b in db.table2 on
                                               new { SUBJECT = a.SUBJECT, CATALOG_NBR = a.CATALOG_NBR, COURSETITLE = a.COURSETITLE.ToString() } equals
                                               new { SUBJECT = b.SUBJECT, CATALOG_NBR = b.CATALOG_NBR, COURSETITLE = b.COURSETITLE.ToString() } into ab
                                               from x in ab.DefaultIfEmpty()
                                               select new joinedTable()
                                               {
                                                   ID = a.ID,
                                                   SUBJECT = a.SUBJECT,
                                                   CATALOG_NBR = a.CATALOG_NBR,
                                                   COURSETITLE = a.COURSETITLE,
                                                   DESCR = x==null?"":x.DESCR
                                               }.AsQueryable();
    

    我不确定,但尝试一下希望它会起作用。

    【讨论】:

      猜你喜欢
      • 2021-09-12
      • 1970-01-01
      • 2015-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多