There are a lot of questions on SO already about Left joins in Linq, and the ones I've looked at all use the join keyword to achieve the desired end.
This does not make sense to me. Let's say I have the tables Customer and Invoice, linked by a foreign key CustomerID on Invoice. Now I want to run a report containing customer info, plus any invoices. SQL would be:
select c.*, i.*
from Customer c
left join Invoice i on c.ID = i.CustomerID
From what I've seen of the answers on SO, people are mostly suggesting:
var q = from c in Customers
join i in Invoices.DefaultIfEmpty() on c.ID equals i.CustomerID
select new { c, i };
I really don't understand how this can be the only way. The relationship between Customer and Invoice is already defined by the LinqToSQL classes; why should I have to repeat it for the join clause? If I wanted an inner join it would simply have been:
var q = from c in Customers
from i in c.Invoices
select new { c, i };
without specifying the joined fields!
I tried:
var q = from c in Customers
from i in c.Invoices.DefaultIfEmpty()
select new { c, i };
but that just gave me the same result as if it were an inner join.
Is there not a better way of doing this?
While the relationship is already defined (both in the database and in the .dbml markup) the runtime cannot automatically determine if it should use that relationship.
What if there are two relationships in the object model (Person has Parents and Children, both relationships to other Person instances). While cases could be special cased, this would make the system more complex (so more bugs). Remember in SQL you would repeat the specification of the relationship.
Remember indexes and keys are an implementation detail and not part of the relational algebra that underlies the relation model.
If you want a LEFT OUTER JOIN then you need to use "into":
from c in Customers
join i in Invoices on i.CustomerId equals c.CustomerId into inv
...
and inv will have type IEnumerable<Invoivce>, possibly with no instances.
What are you talking about? That from i in c.Invoice.DefaultIfEmpty() is exactly a left join.
List<string> strings = new List<string>() { "Foo", "" };
var q = from s in strings
from c in s.DefaultIfEmpty()
select new { s, c };
foreach (var x in q)
{
Console.WriteLine("ValueOfStringIs|{0}| ValueOfCharIs|{1}|",
x.s,
(int)x.c);
}
This test produces:
ValueOfStringIs|Foo| ValueOfCharIs|70|
ValueOfStringIs|Foo| ValueOfCharIs|111|
ValueOfStringIs|Foo| ValueOfCharIs|111|
ValueOfStringIs|| ValueOfCharIs|0|
You may probably want to use the 'into' keyword.
Example
Related
In the code below, I'm wondering why the elements resulting from my left outer join (as in from d in co.DefaultIfEmpty(emptyOrder) where d is the elements of the table returned from co.DefaultIfEmpty(emptyOrder)) don't contain properties from both Customers and Orders, but rather only contains properties from Orders.
I find myself having use two variables to display the required information, c.c and c.d, to be able to access information from Customers and Orders. If I replace c.c.CompanyName by c.d.CompanyName, the compiler says CompanyName is not a property of c.d, which is an Order. What I don't understand is this: isn't d supposed to be an element of the resulting table from joining Customers and Orders? Why then doesn't d contain properties from both Customers and Orders as in SQL where the resulting joined table would display columns from Customers and Orders all into one table?
var query11 = from c in CustomerList
where c.Country == "USA"
join o in OrderList
on c.CustomerID equals o.CustomerID into co
from d in co.DefaultIfEmpty(emptyOrder)
select new { c, d };
foreach (var c in query11) {
sbResult.Append(String.Format("CustID = {0}, Name = {1},
OrderID = {2}, OrderDate = {3:d}\r\n",
c.c.CustomerID, c.c.CompanyName, c.d.OrderID,
c.d.OrderDate));
}
What you're seeing is normal. The whole mass of LINQ there is the left outer join. If you hover the mouse over co, its type is IEnumerable<Order> (or whatever the name of the item class in OrderList is).
The "joined thing" with the properties of both is the anonymous type you select at the end -- all examples of this LINQ left outer join technique return an anonymous type with the "left table" object and the "right table" object -- or else with various properties pulled from each. As in SQL, the fields in the result set are determined by what you select.
You could change select new { c, d } to select new { c.CustomerID, c.CompanyName, d.OrderID, d.OrderDate } and get a cleaner anonymous type for your loop.
I'm trying to do a simple join query in Linqpad, to mimic the following ...
SELECT *
FROM Companies C
JOIN Addresses A
ON A.CompanyID = C.CompanyID
WHERE C.CompanyID = 123
I'm using C# Expression (so no need to Dump, AFAIK), and tried the following unsuccessfully ...
from C in Companies
join A in Addresses on C.CompanyID equals A.CompanyID
where C.CompanyID = 123
select C,A
So the result is "name does not exist in current context"
I suspect it might be because of common field in both tables, or the C,A syntax is basically wrong.
I want to be able to do the splat "*" across both tables. Is this possible?
I believe your select should look like
select new { C, A }
or
select new { Company = C, Address = A }
as you are returning more than one complex object, so it should be wrapped with an anonymous type. Or you can define your type and then set the properties like so
select new MyType { Company = C, Address = A }
I am pretty new to Entity Framework and LINQ and I have an entity with more than 10+ other associated entities (one-to-many relationships). Now, I'm planning to make a search page in my application in which users could select which fields (i.e. those 10+ tables) they want to be considered when searching.
Now, I'm trying to write a query to achieve the above goal. Any help how I could sort this out using LINQ method syntax? I mean, to write a multiple join query based on user's choice. (i.e. which of Class1, Class2, ... to join with main Entity to finally have all the related fields in one place). Below is a sample code (Just a hunch, in fact)
if(somefilter#1)
result = db.Companies.Join(db.Channels, p => p.Id, k => k.CId,
(p, k) => new {Company = p, Channels=k});
if(somefilter#2)
result = result.Join(db.BusinnessType, ........);
if(somefilter#3)
result = result.Join(db.Values, .......);
For complex queries it may be easier to use the other LINQ notation. You could join multiple entities like this:
from myEntity in dbContext.MyEntities
join myOtherEntity in dbContext.MyOtherEntities on myEntity.Id equals myOtherEntity.MyEntityId
join oneMoreEntity in dbContext.OneMoreEntities on myEntity.Id equals oneMoreEntity.MyEntityId
select new {
myEntity.Id,
myEntity.Name,
myOtherEntity.OtherProperty,
oneMoreEntity.OneMoreProperty
}
You can join in other entities by adding more join statements.
You can select properties of any entity from your query. The example I provided uses a dynamic class, but you can also define a class (like MyJoinedEntity) into which you can select instead. To do it you would use something like:
...
select new MyJoinedEntity {
Id = myEntity.Id,
Name = myEntity.Name,
OtherProperty = myOtherEntity.OtherProperty,
OneMoreProperty = oneMoreEntity.OneMoreProperty
}
EDIT:
In case when you want to have conditional joins you can define MyJoinedEntity with all the properties you will need if you were to join everything. Then break up the join into multiple methods. Like this:
public IEnumerable<MyJoinedEntity> GetEntities() {
var joinedEntities = from myEntity in dbContext.MyEntities
join myOtherEntity in dbContext.MyOtherEntities on myEntity.Id equals myOtherEntity.MyEntityId
join oneMoreEntity in dbContext.OneMoreEntities on myEntity.Id equals oneMoreEntity.MyEntityId
select new MyJoinedEntity {
Id = myEntity.Id,
Name = myEntity.Name,
OtherProperty = myOtherEntity.OtherProperty,
OneMoreProperty = oneMoreEntity.OneMoreProperty
};
if (condition1) {
joinedEntities = JoinWithRelated(joinedEntities);
}
}
public IEnumerable<MyJoinedEntity> JoinWithRelated(IEnumerable<MyJoinedEntity> joinedEntities) {
return from joinedEntity in joinedEntities
join relatedEntity in dbContext.RelatedEntities on joinedEntity.Id equals relatedEntity.MyEntityId
select new MyJoinedEntity(joinedEntity) {
Comments = relatedEntity.Comments
};
}
I have 3 data tables: a; b; and c. In this I need to write Join Query Dynamically using LINQ.
The Selecting columns given by customer and Condition columns also given customer at run time.
So I need to create queries dynamically. Please check below example. Because I don't know which table they want and which column also
For example
Select a.c1,a.c2,b.c1,b.c2 From a Left Join b on a.c1=b.c1
Select c.c1,c.c2,a.c1,a.c2 From c Left Join a on c.c3=a.c1
Select a.c1,a.c2,b.c1,b.c2,c.c1,c.c2 From a Left Join b on a.c2=b.c2 Left join c on c.c1=a.c1
Like I need create different set of queries. Please help me on this.
You could use either System.Linq.Dynamic(ScottGu's blog article and nuget) in case of dynamic where clause:
var results = (from fruit in fruits
join car in cars on fruit.Id equals car.Id
select new { fruit, car })
.AsQueryable()
.Where("fruit.ColA != car.ColA")
.Where("fruit.ColB == car.ColB");
Or dynamicaly build expressions this using extensions from PredicateBuilder writen by #joe-albahari. For example:
var predicate =
PredicateBuilder
.True<Tuple<Product, Product>>()
.And(t => t.Item1.ColA != t.Item2.ColA)
.And(t => t.Item1.ColB == t.Item2.ColB)
.Compile();
(from fruit in fruits
join car in cars on fruit.Id equals car.Id
select Tuple.Create(fruit, car))
.Where(predicate)
.Dump();
ps: full code available at gisthub
I have a fairly complicated join query that I use with my database. Upon running it I end up with results that contain an baseID and a bunch of other fields. I then want to take this baseID and determine how many times it occurs in a table like this:
TableToBeCounted (Many to Many)
{
baseID,
childID
}
How do I perform a linq query that still uses the query I already have and then JOINs the count() with the baseID?
Something like this in untested linq code:
from k in db.Kingdom
join p in db.Phylum on k.KingdomID equals p.KingdomID
where p.PhylumID == "Something"
join c in db.Class on p.PhylumID equals c.PhylumID
select new {c.ClassID, c.Name};
I then want to take that code and count how many orders are nested within each class. I then want to append a column using linq so that my final select looks like this:
select new {c.ClassID, c.Name, o.Count()}//Or something like that.
The entire example is based upon the Biological Classification system.
Update:
Assume for the example that I have multiple tables:
Kingdom
|--Phylum
|--Class
|--Order
Each Phylum has a Phylum ID and a Kingdom ID. Meaning that all phylum are a subset of a kingdom. All Orders are subsets of a Class ID. I want to count how many Orders below to each class.
I hope this is clear now.
Normally this is done with a group. For example:
from k in db.Kingdom
join p in db.Phylum on k.KingdomID equals p.KingdomID
where p.PhylumID == "Something"
join c in db.Class on p.PhylumID equals c.PhylumID
group c by new { c.ClassID, c.Name } into g
select new { Count = g.Count(), g.Key.ClassID, g.Key.Name };
That will basically count how many entries you have for each ClassID/Name pair. However, as Winston says in the comments, you're possibly interested in another table (Order) that you haven't told us about. We can't really give much more information until we know what you're doing here. Do you already have a relationship set up for this in LINQ to SQL? Please tell us about the Order table and how it relates to your other tables.
EDIT: Okay, with the modified question, I suspect we can ignore phylum and kingdom completely, unless I'm missing something. (I also can't see how this relates to a many-to-many mapping...)
I think this would work:
from o in db.Order
group o by o.ClassID into g
join c in db.Class on g.Key.ClassID equals c.ClassID
select new { c.ClassID, c.Name, g.Count() };