How to Perform a Cross Join with Linq to SQL

How do you perform a CROSS JOIN with LINQ to SQL?

A cross-join is simply the Cartesian product of two sets. There's no explicit join operator for it.


var combo = from p in people
from c in cars
select new
{
p.Name,
c.Make,
c.Model,
c.Colour
};

SQL to Linq conversion with cross join

Cross joins are generally represented as multiple from clauses in a query expression, or a call to SelectMany in extension method syntax.

So the first part of your query might be:

var query = from systemName in db.Table.Select(x => x.SystemName).Distinct()
from resetCode in db.Table.Select(x => x.ResetCode).Distinct()
...

Left outer joins are usually represented with a "join ... into ..." query, possibly like this:

var query = from systemName in db.Table.Select(x => x.SystemName).Distinct()
from resetCode in db.Table.Select(x => x.ResetCode).Distinct()
join tmp in db.Table on
new { ResetCode = resetCode, SystemName = systemName }
equals new { tmp.ResetCode, tmp.SystemName }
into tmpGroup
select new { ResetCode = resetCode,
SystemName = systemName,
Count = tmpGroup.Count() };

I'm not sure about the Count part, to be honest... I'm not 100% sure what the COUNT(v.ResetCode) does in your original SQL.

How efficient is a cross-join in Linq-to-SQL?

Linq-to-SQL translates the linq query to T-SQL that runs on the database side.

For example, if you write:

from i in myContext.Table1
from j in myContext.Table2
select new {i,j}

Linq-to-SQL will translate that to a T-SQL query similar to:

SELECT * 
FROM Table1, Table2

and then it will serve the resulting anonymous type objects by iterating over the resultset just once.

Hope this makes sense.

How to write a Linq expression for a SQL cross join?

I'd approach it as a multi-part join:

var nonCompiantImmunization =
from p in Persons
from i in Immunizations
let pi = PersonImmunizations.Where(x =>
x.ImmunizationID == i.ID && x.PersonID == p.ID)
where !pi.Any() || pi.Sum(x => x.Doses) < i.RequiredDoses
select new { p, i };

Edit: To make it fit the Expression<Func<Person, bool>> constraint, I suppose you could rephrase it as:

Expression<Func<Person, bool>> nonCompliantImmunization = 
person => (
from i in Immunizations
let pi = PersonImmunizations.Where(x =>
x.ImmunizationID == i.ID && x.PersonID == person.ID)
where !pi.Any() || pi.Sum(x => x.Doses) < i.RequiredDoses
select true
).Any();

Nice, clean cross join in Linq using only extension methods

One way would be:

var z2 = xs.SelectMany(x => ys, (x, y) => new {x, y});

Working with Cross Context Joins in LINQ-to-SQL

I've had to do this before, and there are two ways to do it.

The first is to move all the servers into a single context. You do this by pointing LINQ-to-SQL to a single server, then, in that server, create linked servers to all the other servers. Then you just create views for any tables you're interested from the other servers, and add those views to your context.

The second is to manually do the joins yourself, by pulling in data from one context, and using just the properties you need to join into another context. For example,

int[] patternIds = SessionDataProvider.Instance.ResultDataContext.Results.Select(o => o.patternId).ToArray();
var results = from p in PatternDataContext.Patterns
where patternIds.Contains(p.PatternId)
select p;

Though the first is easier to work with, it does have its share of problems. The problem is that you're relying on SQL Server to be performant with linked servers, something it is notoriously bad at. For example, consider this query:

var results = from p in DataContext.Patterns
join r in DataContext.LinkedServerResults on p.PatternId equals r.PatternId
where r.userId = 10;

When you enumerate this query, the following will occur (let's call the normal and linked servers MyServer and MyLinkedServer, respectively)

  1. MyServer asks MyLinkedServer for the Results
  2. MyLinkedServer sends the Results back to MyServer
  3. MyServer takes those Results, joins them on the Patterns table, and returns only the ones with Results.userId = 10

So now the question is: When is the filtering done - on MyServer or MyLinkedServer? In my experience, for such a simple query, it will usually be done on MyLinkedServer. However, once the query gets more complicated, you'll suddenly find that MyServer is requesting the entire Results table from MyLinkedServer and doing the filtering after the join! This wastes bandwidth, and, if the Results tables is large enough, could turn a 50ms query into a 50 second query!

You could fix unperformant cross-server joins using stored procedures, but if you do a lot of complex cross-server joins, you may end up writing stored procedures for most of your queries, which is a lot of work and defeats part of the purpose of using L2SQL in the first place (not having to write a lot of SQL).

In comparison, the following code would always perform the filtering on the server containing the Results table:

int[] patternIds = (from r in SessionDataProvider.Instance.ResultDataContext.Results
where r.userId = 10
select r.PatternId).ToArray();
var results = from p in PatternDataContext.Patterns
where patternIds.Contains(p.PatternId)
select p;

Which is best for your situation is up to your best judgement.


Note that there is a third potential solution which I did not mention, as it is not really a programmer-solution: you could ask your server admins to set up a replication task to copy the necessary data from MyLinkedServer to MyServer once a day/week/month. This is only an option if:

  • Your program can work with slightly stale data from MyLinkedServer
  • You only need to read, never write, to MyLinkedServer
  • The tables you need from MyLinkedServers are not exorbitantly huge
  • You have the space/bandwidth available
  • Your database admins are not stingy/lazy

How do you code a cross join in LINQ?

var res = from t1 in table1
from t2 in table2
select new
{
KEY = t1.KEY,
DATA1 = t1.DATA,
DATA2 = t2.DATA,
};

Cross join or full join in LINQ to SQL query

SELECT CAST(l1.x as varchar(4)) + CAST(l2.x as varchar(4))+ CAST(l3.x as varchar(4)) + CAST(l4.x as varchar(4))
FROM LINQ as l1, LINQ as l2, LINQ as l3, LINQ as l4
ORDER BY l1.x, l2.x, l3.x, l4.x

sqlfiddle here

Translate a SQL query to linq to entity with a cross join

There is no special "cross join" operator in LINQ, the construct is simple no join like this

from a in tableA
from b in tableB
...

Your SQL query should be translated to something like this (not tested)

var query =
from allds in (from discount in db.Discounts
from sku in db.SKUs
select new { DiscountId = discount.Id, SKUId = sku.Id }
).Distinct()
join ds in db.DiscountSKUs
on new { allds.DiscountId, allds.SKUId } equals new { ds.DiscountId, ds.SKUId }
into discountSKUs
from ds in discountSKUs.DefaultIfEmpty()
group new { allds, ds } by new { allds.DiscountId, allds.SKUId } into g
select new
{
g.Key.DiscountId,
g.Key.SKUId,
HasPair = g.Any(e => e.ds != null)
};

Cross Join in Entity framework Lambda Expressions

You could do this:

var query= from t1 in context.MY_TEST_TABLE1
from t2 in context.MY_TEST_TABLE2
where t1.firstname == t2.name
select new { Table1Id= t1.ID, FirstName= t1.firstname, Table2Id=t2.ID,Name= t2.name};

Another way to do a cross join in Linq to Entities is using SelectMany extension method:

var query= context.MY_TEST_TABLE1.SelectMany(
t1=>context.MY_TEST_TABLE2
.Where(t2=>t1.firstname == t2.name)
.Select(t2=>new {
Table1Id= t1.ID,
FirstName= t1.firstname,
Table2Id=t2.ID,
Name= t2.name
})
);


Related Topics



Leave a reply



Submit