Linq code for joining many to many tables - c#

I'm new at linq and need for your advice.
I created three tables.
STUDENT ---- STUDENT_COURSE ----- COURSES
I simply want to list which students are taking which courses.
If I'm using dbml to doing this, I get the result in somehow like below.
var takencourses = from sc in dbe.STUDENT_COURSEs
join s in dbe.Students on sc.SID equals s.ID
join c in dbe.COURSEs on sc.CID equals c.Id
select new { s.NAME, s.SURNAME, c.COURSENAME};
dataGridView1.DataSource = takencourses;
But I'm not able to run this with Entity Data Model.
When I'm adding entity data model STUDENT_COURSE table is disappearing and its adding references on the tables like below.
Because I didn't have the STUDENT_COURSE table I couldn't write the LINQ for joining Student and Courses tables to get the result.
I simply want to take NAME, SURNAME, COURSENAME from Entity Data Model.
So how can I do it with using Entity Data Model?
What should be the equivalent lambda code for this?
For Example I tried something like this dbe.Students.SelectMany(s => s.STUDENT_COURSEs).ToList() but I didn't find the correct result.
If I'm going to working on 100.000 rows, what will be the best choice for performance issues?
Thanks for your answers.

Related

How to select data from entity framework without selecting its icollection(foreign table)

I am using C# to select data from my database. Now i have two table, the first one is aspnetuser, the second one is aspnetuserroles, the aspnetuserroles have the foreign key linkage with aspnetuser table, when i perform the following query
db.AspNetUsers.ToList()
the aspnetroles data will appeared in the aspnetusers data. This will cause my datatable unable to display its data because datatable expect one value in one column parameter. If the aspnet roles data inside that json, it will appear as multiple row and datatable dont accept it.. If i remove that foreign key linkage, my datatable will display without any error.
In this case, what i want is, how to select aspnetusers table without pulling out its foreign table. For eg
db.AspNetUsers.Select(x=>x.AspNetUsers).ToList();
Turn off the LazyLoading. So that the children will not be fetched automatically.
try doing something like this (good for keeping the return object light and leave behind any unwanted columns):
(I have just made up some col name, but you get the idea.)
var result = (from a in db.AspNetUsers
select new AspNetUser { Name = a.Name,
othercol1 = a.othercol1,
othercol2 = a.othercol2,
}).ToList();
Footnote: In reality it is generally not good practice to return the actual db Entity to the front end so you might want to have your own Data Transfer Objects (DTO).
You configured that in the mappings using the Fluent API's methods
HasOptional
HasMany
Ignore
etc. But normally, I create schema-bound views in database and then map that in EF. It works really well in cases when we're only interested in a flattened query without all the joints.
Or use Linq to EF projections as JonhB's answer...
var result = (from a in db.AspNetUsers
select new AspNetUser { Name = a.Name,
...
}).ToList();
Just make sure you don't call ToList on db.AspNetUsers because that would materialize the query on AspNetUsers and all it's foreign key references and as result the projection is done in-memory after the query returns

adding object entity framework using many to many relationship

I have a database like lets say a class Student and a class Course. These two have many to many relationship through a join table, holding ids of these two tables which is hidden in EF the way it supposed to.
First if I add two courses to a student. Like
John.classes.Add(math); John.classes.Add(physics) where 'John', math and physics are objects of their respective classes. When i save changes, everything happens the ways it should happen. An entry in students table, two entries in courses table and two entries in StudentCourses join table. All good.
But then, when i add another student say 'Bob' with same two classes. Bob.classes.Add(math); Bob.classes.Add(physics);It should add a row in students table adding Bob and two rows in StudentCourses join table. This doesn't happen. A row is added to students table but no rows are being added to StudentCourses table giving error of duplicate entry in courses table. Entity Framework is not adding courses because math and physics already exist in courses table but it should add two entries in StudentCourses join table.
A work around this is by adding an id column in join table and use this table as normal table and manually add entries in StudentCourses table. But i dont want to do this, I want to know the actual solution.
Thanks
i solved it by
team ct = context.teams.Find(club.id);
if (ct == null)
{ comp.teams.Add(club); }
else
{ ct.competitions.Add(comp); }
context.SaveChanges();
where comp is competition object.
I am sure this is not the actual solution but just a way around. This can't be...

working with multiple tables

I have a c# project where I am using a MS access database, and I am trying to put some items from two (related) tables, in the same listView.
This is the code that I have:
Where it sais "none" is the place where I want to put an item from the other table, but i don't know how. Since they have a relationship I thought that was possible to call items from one table or another.
Please note that I am fairly new to c# and working with databases.
You should join the two tables together to get the unified result.
You could do something like this:
select c.*
, s.otherFieldYouNeed
from ClientsT c
join SomeOtherTable s
on c.someId = s.someId
since the two table are related you can use a join query to get the desired result:
select FirstName,LastName,'none',CellPhone,ClientID from Clients inner join mySecondTable
on Clients.mysharedField=mySecondTable.mysharedField
select FirstName,LastName,(select none from SecondTable where Clients.Field= SecondTable.Field),CellPhone,ClientID from Clients
Try altering your query to include this information. Something like:
Select FirstName, LastName, ColumnFromOtherTable, CellPhone, ClientsT.ClientID
from ClientsT, OtherTable where ClientsT.ClientID=OtherTable.ClientID
Of course, in order to do this, you have to have a corresponding ID field in both tables.

Order by a field which is a Navigation Property to an Entity - Linq to Entity

I've got a scenario where I will need to order by on a column which is a navigation property for the Users entity inside my EF model.
The entities:
Users --> Countries 1:n relationship
A simple SQL query would be as follows:
SELECT UserId, u.Name, c.Name
FROM users u join countries c on u.CountryId = c.CountryId
ORDER BY c.Name asc;
So then I tried to replicate the above SQL query using Linq to Entities as follows - (Lazy Loading is enabled)
entities.users.OrderBy(field => field.country.Name).ToList();
But this query does not return my countries sorted by their name as the native SQL query above does.
However I continued a bit more and did the following:
var enumeratedUsers = entities.users.AsEnumerable();
users = enumeratedUsers.OrderBy(fields => fields.country.Name).ToList();
But ordering on the enumeratedUser object for about 50 records took approx. 7seconds
Is there a better way how to omit the Enumerable and without returning an anonymous type?
Thanks
EDIT
I just forgot to say that the EF provider is a MySQL one not a MS SQL. In fact I just tried the same query on a replicated database in MS SQL and the query works fine i.e. the country name is ordered correctly, so it looks like I have no other option apart from getting the result set from MySQL and execute the order by from the memory on the enumerable object
var enumeratedUsers = entities.users.AsEnumerable();
users = enumeratedUsers.OrderBy(fields => fields.country.Name).ToList();
This is LINQ to Objects not LINQ to Entities.
Above Order By clause will call OrderBy defined in Enumerable
That is ordering will be done in memory. Hence it will take long time
Edit
It looks like a MySQL related issue
You may try something like this.
var users = from user in entities.users
join country in entities.Country on user.CountryId equals country.Id
orderby country.Name
select user;
entities.users.OrderBy(field => field.country.Name).ToList();
But this query does not return my countries sorted by their name as the native
SQL query above does.
Yes, it does not return Countries but only Users sorted by the name of country.
When this query is executed, the following sql is sent to DB.
SELECT u.*
FROM users u join countries c on u.CountryId = c.CountryId
ORDER BY c.Name asc;
As you can see, the result does not include any fields of countries. As you mentioned the lazy loading, countires are loaded through it when needed. At this time, countries are ordered as the order you call it through the lazy loading. You can access countries through the Local property of a entity set.
This point tells you that if you want user sorted by the name of country and also countires sorted by the name, you need the eagerly loading as #Dennis mentioned like:
entities.users.Include["country"].OrderBy(field => field.country.Name).ToList();
This is converted to the following sql.
SELECT u.*, c.*
FROM users u join countries c on u.CountryId = c.CountryId
ORDER BY c.Name asc;
Have you tried using Include?
entities.users.Include["country"].OrderBy(field => field.country.Name).ToList();
SOLUTION
Since I had both columns named Name in both Countries and Users table MySQL Connector was generating this output when order by country.Name was executed:
SELECT `Extent1`.`Username`, `Extent1`.`Name`, `Extent1`.`Surname`, `Extent1`.`CountryId`
FROM `users` AS `Extent1` INNER JOIN `countries` AS `Extent2` ON `Extent1`.`CountryId` = `Extent2`.`CountryId`
ORDER BY `Name` ASC
therefore this will result in ordering on the users.Name rather countries.Name
However MySQL have release version 6.4.3 .NET connector which has resolved a bunch of issues one of them being:
We are also including some SQL generation improvements related to our entity framework provider. Source: http://forums.mysql.com/read.php?3,425992
Thank you for all your input. I tried to be clear as much as possible to help others which might encounter my same issue.

Querying a join table using LINQ

Okay this could very likely be a silly question. I am using Entity Framework Code First. I have two classes, User and Event, that have a Many-To-Many relationship. When EF generates my database tables, it creates a join table, which I call Users_Events. This table has two columns, User_ID and Event_ID. Everything is fine so far.
I want to pull an Event from my database and serialize it to JSON. This also works perfectly except I cannot pull an Event's Users because this would create a circular reference. What I want to do here is query my join table and get all the User_IDs that have an associated Event_ID equal to the ID of the Event I am serializing.
How can I do this?
I don't know exactly what you want to end up with in your JSON, but I suspect you want to select into a new anonymous type and serialize that instead. Something along these lines maybe:
from e in myContext.Events
where e.ID = 123
select new {
Event = e,
UserIDs = (from u in e.Users select u.ID)
}

Categories

Resources