简体   繁体   中英

Join Tables with Different DataType in Linq

I have two tables that I need to do left outer join table1 to table2, but table1 coursetitle is VARCHAR(1000) and table2 coursetitle is text datatype. I used ToString() for both fields and I still get errors. Below is my join query:

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 Error:

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

i am not sure, but try it hope it will work.

Use a pre-select to make sure that the keys on which you want to join are equal:

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

Now both JoinKeys are exactly the same type. Note: he queries are not executed yet, the database is not contacted, only the Expression of the query is adjusted.

Whenever you need "Customers with their Orders", "Schools with their Students", "Rows from table1 with their rows from table2", consider to use one of the overloads of GroupJoin , instead of Join. I usually use the overload with a parameter resultSelector, so I can fine tune my results.

To get the table1 rows, each with its zero or more matching table2 rows, use 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(),
    });

In the example above the result seems a bit strange. That is because I don't know what table1 and table2 are. If you would do the same to get "Customer and their Orders", the result would look very natural:

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

Apart from that it feels more natural to get "table1 items with their matching table2 items" than a sequence of combinations of "a table1 item with a matching table 2 item", one of the advantages of a groupjoin is that the item1 properties are transferred only once.

If School[10] has 2000 Students, it is way more efficient to transfer the data of School[10] only once, than to transfer the same school data once for every of its 2000 students.

If you really want a flattened end result, use SelectMany.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM