How to use a JOIN in a LINQ query - linq

I have the following table structure, which is imported into an Entity Framework project:
(NOTE: I mislabled T1Name as T2Name in Table1)
alt text http://digitalsamurai.us/images/drawing2.png
I have labeled the Entity Objects. The many-to-many joint table Table5, is represented as an EntityCollection<Entity4> in Entity3, and as an EntityCollection<Entity3> in Entity4 (EntityCollection<T> implements IEnumerable<T>, so it can be queried). I need to construct a result set that is:
T1Name, T2Name, T3Name
This will result in repeat entries for T1Name, and T2Name.
Could someone show me how to write this LINQ query?
Thank you for any help.

var q = from e3 in Context.Table3
from e4 in e3.Table4s // that's your many-to-many
select new
{
Name3 = e3.T3Name,
Name2 = e4.Table2.T2Name,
Name1 = e4.Table1.T1Name // presuming Table1.T2Name in your diagram is a typo
};
"Dot notation":
var q = Context.Table3
.SelectMany(e3 => e3.Select(e4 =>
new {
Name3 = e3.T3Name,
Name2 = e4.Table2.T2Name,
Name1 = e4.Table1.T1Name
});
Notice I didn't use join at all. That's on purpose; you don't need it here.

Related

Filter list having two Tables join data in Entity Framework

I have two tables..
Student (StudentId,Name,FatherName)
Qualification (QualificationId,StudentId,DegreeName)
I have got data like this..
var myList = (from c in entities.Students
join q in entities.Qualifications on c.StudentId equals q.StudentId
select new {c.Name,c.FatherName,q.DegreeName}).ToList();
Now i want to filter myList more.. How can i do it, like..
var filteredList = myList.Select(c=> new Student
{
Name=c.Name,
FatherName=c.FatherName
//Degree=C.Degree
}).ToList();
The above Linq Query is not working if i want to get DegreeName also, My Question is how to further Filter myList.
Thanks.
var filteredList = myList.Where(i => i.FatherName == "Shahid").ToList();
Keep in mind since you called ToList() on the original query you are now filtering in memory. If you want to filter in the database then remove the ToList() on the first query and do it like this:
var myList = from c in entities.Students
join q in entities.Qualifications on c.StudentId equals q.StudentId
select new {
c.Name,
c.FatherName,
q.DegreeName
};
var filteredInDatabase = myList.Where(i => i.FatherName == "Shahid").ToList();

linq to sql "All" operator type query

String[] codes = new[] {"C1", "C2" }
Below is the schema for SomeEntity
fkey code
--------------
f1 C1
f1 C2
f2 C2
f2 C3
f2 C4
f3 C5
I have to write queries that can get all the entities based on 2 condition -
1) does the entity have any of the codes
2) does the entity have all the codes
Below is what i wrote for 1st condition
-----------------------------------------
from f in dc.GetTable<SomeEntity>
where codes.Contains(f.code)
select f;
I tried to write 2nd codition by using All operator but "All" operator is not valid for linq to sql.
Question: How to write a query that will return only those entities that have all the codes ?
var codeCount = dc.GetTable<SomeEntity>.Distinct(e => e.Code);
var matching = (from f in dc.GetTable<SomeEntity>
group f by f.Key into grouped
select new { f.Key, values = grouped}).Where(v => v.values.Count() == codeCount);
Probably a hideous query, a stored proc mapped to a function on the data context might be a better solution to be honest
You could probably do the codeCount as let binding in the query and carry on the linq statement rather than close out to the .Where call. Not sure if it'd make it more performant but would save an extra trip to the DB
Try this.
Group by fkey (which will create distinct fkeys)
Filter the groups where
All members of the list of codes are contained within the codes of that group
See below
var matching = dc.GetTable<SomeEntity>()
.GroupBy(e => e.fkey)
.Where(group => codes.All(c =>
group.Select(g => g.code).Contains(code)))
.Select(group => group.Key);

LINQ queries with many-to-many tables in Entity Data Model

I'm trying to use LINQ to query the following Entity Data Model
based on this db model
I'd like to be able to pull a list of products based on ProductFacets.FacetTypeId.
Normally, I'd use joins and this wouldn't be a problem but I don't quite understand how to query many-to-many tables under the Entity DataModel.
This is an example sql query:
select p.Name, pf.FacetTypeId from Products p
inner join ProductFacets pf on p.ProductId = pf.ProductId
where pf.FacetTypeId in(8, 12)
Presuming EF 4:
var facetIds = new [] { 8, 12 };
var q = from p in Context.Products
where p.FacetTypes.Any(f => facetIds.Contains(f.FacetTypeId))
select p;
In EF (assuming the mapping is done correctly), joins are hardly ever used; navigation properties are used instead.
Your original SQL returns a tuple with repeated Name entries. With LINQ, it's often easier
to "shape" the queries into non-tuple results.
The following should be the same as the SQL, only instead of returning (Name, FacetTypeId) pairs with repeated Names, it will return a type that has a Name and a sequence of FacetTypeIds:
var facetIds = new [] { 8, 12 };
var result = from p in db.Products
select new
{
p.Name,
FacetTypeIds = from pf in p.FacetTypes
where pf.FacetTypeId == 8 || pf.FacetTypeId == 12
select pf.FacetTypeId,
};

How to write linq query based on EF?

Suppose I have three tables:
Person(pid, ...)
PersonAddress(pid, aid,...)
Address(aid, ...)
Then I want to get the person address like sql:
select a.* from address a join PersonAddress pa on a.addressID=pa.addressID
where pa.personID = myPersonID
Use Entity Framework to create Entity model, then want to write a linq equivalent as above sql.
I tried it in following way:
var addresses = this.GetAddress();
var personaddresses = this.GetPersonAddress();
var query = from ad in addresses
from pa in personaddresses
where ((ad.AddressID == pa.AddressID)&&(pa.PersonID==person.personID))
select ad;
but I got error. Or I try to start from:
var result = this.Context.Address;
var result = result.Join .... //how to write linq in this way?
How to write the linq?
This is untested but if you have all of your relationships setup and you create the model (I have used Model as the name for this) from this you should be able to use the following:
var values = this.Model.Address.Select(a => a.PersonAddress.Where(pa => pa.Id == myPersonID));
You almost never use join in LINQ to Entities.
Try:
var q = from p in Context.People
where p.PersonId == personId
from a in p.Addresses // presumes p.Addresses is 1..*
select a;
Assuming you have three entities: Person, PersonAddress and Address, here is a query that should meet your needs (this example assumes an Entity Framework context named context):
var values = context.PersonAddress.Where(pa => pa.Person.PersonId == myPersonId).Select(pa => pa.Address);
However, if the PersonAddress table exists as a pure many-to-many relationship table (i.e. contains only keys), you'd be better off setting up your Entity Framework model in such a way that the intermediate table isn't necessary, which would leave you with the much simpler:
var values = context.Person.Where(p => p.PersonId == myPersonId).Addresses;
Based on the additional feedback
Because you need to include the country table, you should originate your query from the Address table. In that case:
var values = context.Address.Where(a => a.PersonAddress.Where(pa => pa.Product.Id == myProductId).Count() > 0)
To include the Country table in the result:
var values = context.Address.Include("Country").Where(a => a.PersonAddress.Where(pa => pa.Product.Id == myProductId).Count() > 0)

How to write linq to get data from different tables?

Suppose I have 3 tables: A(aid, ...), B(bid, ...) Relationship(aid, bid, ...)
Then I have a aid as parameter, I want to get the result from b. If use SQL, will be like
select b.* from B join Relationship on b.bid = Relationship.bid
where relationship.aid = aid_param
how to write linq with same result as above SQL. (the foreign key was not created correctly in this case)?
Assuming that you've used the designer to add your tables to the LINQ data context and you have either foreign key relationships defined in the database or have hand-coded the associations in the designer, you should simply be able to reference the B table and it's EntitySet of Relationship properties, filtered by your parameter, and check if there are any matches.
var relationships = db.B.Any( b => b.Relationships.Where( r => r.aid == aid_param ) );
var bQuery = from r in MyContext.Relationship
where r.aid == aid_param
select r.B;
If you don't have a relationship set in the model, then u can:
var bQuery = from b in myContext.B
where myContext.Relationship
.Any( r => r.aid == aid_param && b.bid == r.bid)
select b;
var output =
from b
from Relationship
where (b.bid = Relationship.bid,
relationship.aid = aid_param)

Resources