How do i get an inner join in a WCF Data Service - linq

Lets say i have 2 tables, table1 and table2, with a shared key "id"
if i want an inner join of those two tables using sql, i'd do something like
select id, x, y, z
from table1
inner join table2
on table1.id = table2.id
I now get rows in table 1 that only intersect occur in table 2.
how do i get the equivalent in wcf data service/odata linq syntax?
i'm expecting something like:
var q = (from t in svc.Table1.Expand("Table2")
where t.Table2.Any()
select t) as DataServiceQuery<Table1>;
but that gets me an exception about Any().
I've tried .Join and that isn't supported either.
I've tried .Count and that fails too.
.Intersect looks like it only takes another enumerable, so that doesn't look like what i want...
i think i'm missing something really obvious or simple...
Edit: this appears to be a dup of this How do I use OData Expand like a SQL join?

Take a look at the answers to this type of question. The current version of WCF Data Services (OData) does not support joins even if your underlying data contract does (i.e. if you're layering on top of Entity Framework 4 for instance).

The more recent releases of WCF Data Services now include Any/All support. See What's New in WCF Data Services 5.0

Currently the OData protocol (and thus WCF Data Services) doesn't support any/all operations. It also doesn't support arbitrary joins, although some joins can be expressed as navigations.
Your query is currently not supported, but we're looking into adding support for the any/all operations. Take a look at this proposal if that would fulfill your needs:
http://www.odata.org/blog/support-for-any-and-all

Is WCF in play here? To link two objects from two tables/lists, I'd do this:
var result =
from o1 in Table1
join o2 in Table2 on o2.id equals o1.id

Related

making inner join linq or using [table].[joiningTable].column is the same?

I have recently started working on linq and I was wondering suppose I have 2 related tables Project (<=with fkAccessLevelId) and AccessLevel and I want to just select values from both tables. Now there are 2 ways I can select values from these tables.
The one i commonly use is:
(from P in DataContext.Projects
join AL in DataContext.AccessLevel
on P.AccessLevelId equals AL.AccessLevelId
select new
{
ProjectName = P.Name,
Access = AL.AccessName
}
Another way of doing this would be:
(from P in DataContext.Projects
select new
{
ProjectName = P.Name,
Access = P.AccessLevel.AccessName
}
What i wanted to know is which of these way is efficient if we increase the number of table say 5-6 with 1-2 tables containing thousands of records...?
You should take a look at the SQL generated. You have to understand that there are several main performance bottle necks in a Linq query (in this case I assume a OMG...Linq to SQL?!?!) the usual main bottle neck is the SQL query on the server.
Typically SQL Server has a very good optimizer, so actually, given the same query, refactored, the perf is pretty uniform.
However in your case, there is a very real difference in the two queries. A project with no Access Level would not appear in the first query, whilst the second query would return with a null AccessName. In effect you would be comparing a LEFT JOIN to an INNER JOIN.
TL:DR For SQL Server/Linq to Entity Framework queries that do the same thing should give similar performance. However your queries are far from similar.

Cross-Join Syntax in Entity Framework / IQueryable

I'm trying to deepen my education about IQueryable custom providers and expression trees. I'm interested in custom parsing a cross-join (viz. SelectMany), and I'm trying to understand if that is exactly what EF is doing when it handles this:
var infoQuery =
from cust in db.Customers
from ord in cust.Orders
where cust.City == "London"
select ord;
Allegedly EF can handle cross joins, though the syntax in that link does not look right to me. Then I found a link with the title "Cross Product Queries" for EF. The syntax looks "correct," but the article itself speaks as if these are normal inner joins rather than cross joins.
Indeed, the code snippet above comes from that last article - and leaves me wondering if EF simply says "I know how these two entities are related, so I will form the inner-join automatically."
What is the real story with EF and this alleged "cross join" sample?
footnote
As I try to build my own IQueryable LINQ provider, the educational goal I've set for myself is to make my own query context for the code snippet above, so that when ToList() is called on the query:
A Console.WriteLine() is automatically fired that prints "This is a cross join of:Customer and Order
The == operator is magically converted into a != before the query is fully interpreted (by an ExpressionVisitor perhaps, not sure).
If someone knows of articles or has snippets of code that would speed my educational goal, please do share! :)
Look closely at the syntax:
from cust in db.Customers
from ord in cust.Orders // cust.
select ...
Because of cust.Orders this is a regular inner join. It's even the preferred way to do a join, because it is far more succinct than the regular join statement.
I don't understand the title of this "Cross-Product Queries" article. Firstly, because as far as I know "cross product" applies to three-dimensional vectors not relational algebra. Secondly, because there is not a single cross join in the examples, only inner joins. Maybe what they're trying to say is that the above syntax looks like a cross join? But it isn't, so it's only confusing to use the word so prominently in the title.
This code snippet
from cust in db.Customers
from ord in db.Orders // db.
select ...
is a true cross join (or Cartesian product). If there are n customers and m orders the result set contains n * m rows. Hardly useful with orders and customers, but it can be useful to get all combinations of elements in two sequences. This construct can also be useful if you want to join but also need a second condition in the join, like
from cust in db.Customers
from ord in db.Orders
where cust.CustomerId == ord.CustomerId && ord.OrderDate > DateTime.Today
Which effectively turns it into an inner join. Maybe not the best example, but there are cases where this comes in handy. It is not supported in the join - on - equals syntax.

Doctrine result cache bug with LEFT JOIN ... WITH condition

I tend to find answers before I need to post a question here, but today I can't seem to find out what is wrong.
We're using Doctrine 2.1.2 in a Symfony 2 app, and in a repository we have two methods that use almost the same query.
The only difference between method A and method B is that there is a condition added to a JOIN that is common to both queries.
The problem is that Doctrine seems to use the same result cache for both queries.
When we call method A, method B uses the cache from A, and the other way around.
I have been using expireResultCache(true) and useResultCache(false), to no avail.
Here's what the queries look like:
-- method A
SELECT DISTINCT a, b, c FROM MyBundle:ObjectA a INDEX BY a.id
LEFT JOIN a.fkObjectB b
LEFT JOIN a.fkObjectC c
-- method B
SELECT DISTINCT a, b, c FROM MyBundle:ObjectA a INDEX BY a.id
LEFT JOIN a.fkObjectB b WITH b.some_field IS NULL
LEFT JOIN a.fkObjectC c
When I use getSQL(), I see that they result in different queries as expected. The generated queries, when run independantly in database, do generate different results.
This leads me to believe that it may be an annoying result cache bug, where Doctrine does not cache the conditions for JOINs, but only the table names.
Is this a bug, or is there something I can do?
EDIT Still happening in Doctrine 2.1.6.
I think the problem you have is fixed in Doctrine 2.2. I have similar problem related to result cache and here is my question&answers.
Just to expand on michel v's comment, Doctrine 2 is fetching the same object instance both times via the identity map pattern.
Calling:
EntityManager#clear()
clears the identity map and forces the EntityManager to fetch a fresh copy of the object from the database.

CRM 2011 LINQ query with multiple inner joins and a single WHERE clause (VB .NET)

I am having a great deal of difficuly trying to get LINQ queries working with CRM 2011. The problem occurs whenever I have three or more joined tables (doesn't seem to matter which CRM tables), and I try to add a WHERE clause (doesn't matter on which table I am filtering). If I remove the WHERE clause, the query runs fine and I can loop through the result set. I can also leave the WHERE clause, but remove the third join, and it also works. I have tried this with numerous CRM entities, and get the same error of "The result selector of the 'Join' operation must return an anonymous type of two properties." It appears there is a limitation that if I want to use a single WHERE clause, I am limited to joining only two tables.
I am using the early-bind CRM Context generated code method when issuing the LINQ query. This is code pulled from the CRM SDK examples, except I added the WHERE clause. I cannot find an example anywhere of how to do this.
Dim MyVar = From a In svcContext.AccountSet _
Join c In svcContext.ContactSet On a.PrimaryContactId.Id Equals c.ContactId _
Join l In svcContext.LeadSet On a.OriginatingLeadId.Id Equals l.LeadId _
Where a.Name.Contains("c") _
Select New With {c.FullName}
For Each MyItem In MyVar
Debug.Print(MyItem.FullName)
Next
Thanks for any assistance!
I don't have CRM set up to test to see if it's just a limitation of their provider, but could you try the following:
Dim MyVar = From a In svcContext.AccountSet _
Where a.Name.Contains("c") _
Join c In svcContext.ContactSet On a.PrimaryContactId.Id Equals c.ContactId _
Join l In svcContext.LeadSet On a.OriginatingLeadId.Id Equals l.LeadId _
Select c.FullName
A couple comments: unlike TSQL, the order of operations in LINQ is more flexible. This way you can limit your first table before doing the join (depending on how that is translated by the CRM provider).
Second, do you want to know where "c" is anywhere in the name, or just at the start? If at the start, consider Where a.Name.StartsWith("c")
One other comment, in your Select projection, you're needlessly projecting into an enumerable class. If you're just projecting a single value, you don't need the additional class overhead. Then in your foreach, just do Debug.Print(MyItem) because MyItem is the full name. Also in VB, when using the query syntax, you don't need the New With {...}. If you wanted to project an anonymous type with multiple columns you can do the following in VB just as you would in SQL:
Dim query = From c In Customers
Select C.FullName, C.CompanyName

Outer Joins with Subsonic 3.0

Does anyone know of a way to do a left outer join with SubSonic 3.0 or another way to approach this problem? What I am trying to accomplish is that I have one table for departments and another table for divisions. A department can have multiple divisions. I need to display a list of departments with the divisions it contains. Getting back a collection of departments which each contain a collection of divisions would be ideal, but I would take a flattened result table too.
Using the LINQ syntax seems to be broken (I am new to LINQ though and may be using it wrong), for example this throws an ArgumentException error:
var allDepartments = from div in Division.All()
join dept in Department.All() on div.DepartmentId equals dept.Id into divdept
select divdept;
So I figured I could fall back to using the SubSonic query syntax. This code however generates an INNER JOIN instead of an OUTER JOIN:
List<Department> allDepartments = new Select()
.From<Department>()
.LeftOuterJoin<Division>(DepartmentsTable.IdColumn, DivisionsTable.DepartmentIdColumn)
.ExecuteTypedList<Department>();
Any help would be appreciated. I am not having much luck with SubSonic 3. I really enjoyed using SubSonic 2 and may go back to that if I can't figure out something as basic as a left join.
Getting back a collection of departments which each contain a collection of divisions would be ideal
SubSonic does this for you (if you setup your relationships correctly in the database), just select all Departments:
var depts = Model.Department.All();
There will be a property in each item of depts named Divisions, which contains a collection of Division objects.

Resources