在 Linq 中连接具有不同数据类型的表

Join Tables with Different DataType in Linq

我有两个表需要对表 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();

错误:

"The data types varchar and text are incompatible in the equal to operator."

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

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

使用 pre-select 确保要加入的键相等:

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

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

每当您需要“客户及其订单”、“学校及其学生”、“来自 table1 的行及其来自 table2 的行”时,请考虑使用 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 item", groupjoin 的优点之一是 item1 属性只传输一次。

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

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