I have two tables:
Student Conference
+----+------+ +----+-------+---------------+
| id | name | | id | name | ref_studentId |
+----+------+ +----+-------+---------------+
| 1 | jack | | 1 | Rose | 1,12 |
| 2 | kai | | 2 | White | 12 |
| 3 | wind | | 3 | Black | 1,12,12356 |
+----+------+ +----+-------+---------------+
And I want to join them together with studentid or search for studentid in conference table.
You can use the LINQ Join method to achieve what you want:
var result = dataContext.Students.Join(dataContext.Conferences,
st => st.id,
cf => cf.ref_studentId,
(student, conference) => new { ... });
Although I would strongly recommend using the Entity Framework Navigation Properties, using which the above can be done more easily:
var result = dataContext.Student.Include(st => st.conference);
Update:
Please note that the above LINQ Query will fail to execute unless you will fix your Conference Table design, which is against SQL Normalization Forms (specifically the 1st Normal Form), saying that:
Each sell should be single-valued.
That means that you shouldn't have a comma (or any other character) separated values in your table columns.
To make the above query work, you have to make the ref_studentId contain only a single value for the StudentId:
Conference
+----+--------+-----------+
| ID | Name | StudentId |
+----+--------+-----------+
| 1 | Rose | 1 |
| 2 | Rose | 12 |
| 3 | White | 12 |
| 4 | Black | 1 |
| 5 | Black | 12 |
| 6 | Black | 12356 |
+----+--------+-----------+
But to be honest, this one too will not match the SQL Normalization rules.
Specifically, the 2nd Normal Form, saying that:
All Attributes (non-key columns) should be dependent on a Key.
And the 4th Normal form, saying that:
There should be no multi-value dependencies (Rose ⟶ 1, Rose ⟶ 12)
The correct solution would be to create another table for the Student⟶Conference relations.
Conference ConferencesStudents
+----+-------+ +----+--------------+-----------+
| ID | Name | | ID | ConferenceID | StudentId |
+----+-------+ +----+--------------+-----------+
| 1 | Rose | | 1 | 1 | 1 |
| 2 | White | | 2 | 1 | 12 |
| 3 | Black | | 3 | 2 | 12 |
+----+-------+ | 4 | 3 | 1 |
| 5 | 3 | 12 |
| 6 | 3 | 12356 |
+----+--------------+-----------+
Now, for this one the LINQ query will be:
dataContext.ConferencesStudents.Join(dataContext.Students,
cf => cf.ConferenceID,
st => st.ID,
(conferencesStudents, student) => new { conferencesStudents, student })
.Join(dataContext.Conferences,
cfSt => cfSt.conferencesStudents.ConferenceID,
cf => cf.ID,
(cfSt, conference) =>
new
{
Student = cfSt.student,
Conference = conference
});
Note: for the above, I've used the Anonymous Types just for demonstration and my strong advice would be to use real class Models instead.
OR
By using the same Navigation Properties (in case if you correctly had defined the EF relations) you can have a simpler version:
dataContext.ConferenceStudents.Include(cf => cf.Conferences)
.Include(cf => cf.Students)
Update 2:
I hate to say it but there is a kind of workaround in case if you can't change the Database design:
var results = (
from c in dataContext.Conference.ToList() // populating all Conferences
from s in dataContext.Students.ToList() // populating all Students
where c.ref_studentId.Split(',').Contains(s.id.ToString())
select new
{
Student = s,
Conference = c
}).ToList();
Note: this WILL NOT BE EFFECTIVE from the application performance perspective.
The better alternative compared to the above could be to write Stored Procedure and call it from the EF.
I have prepared a fiddle for you - if there are any questions feel free to ask.
Btw: This solution solves your question. The data-structure itself is ugly and should be normalized.
void Main()
{
var students = new List<Student>
{
new Student { Id = 1, Name = "jack" },
new Student { Id = 12, Name = "kai" },
new Student { Id = 12356, Name = "wind" }
};
var conferences = new List<Conference>
{
new Conference { Id = 1, Name = "Rose", RefIds = "1,12" },
new Conference { Id = 2, Name = "White", RefIds = "12" },
new Conference { Id = 25, Name = "Black", RefIds = "1,12,12356" }
};
var result = students.Select(s => new Tuple<int, Conference[]>(s.Id, conferences.Where(c => c.RefIds.Split(",").Contains(s.Id.ToString())).ToArray()));
}
// Define other methods, classes and namespaces here
public class Student
{
public int Id {get; set;}
public string Name {get;set;}
}
public class Conference
{
public int Id {get; set;}
public string Name {get; set;}
public string RefIds {get; set;}
}
This question already has answers here:
Writing Recursive CTE using Entity Framework Fluent syntax or Inline syntax
(3 answers)
Closed 3 years ago.
I'd like to select only child below CFO and its subchild entities in an Entity Framework select statement.
Here's my table:
+-------+------------+----------+
| OrgId | Name | ParentId |
+-------+------------+----------+
| 1 | COO | |
+-------+------------+----------+
| 2 | CFO | |
+-------+------------+----------+
| 3 | Accountant | 2 |
+-------+------------+----------+
| 4 | Bookkeeper | 3 |
+-------+------------+----------+
| 5 | Controller | 2 |
+-------+------------+----------+
| 6 | Operations | 1 |
+-------+------------+----------+
I'd like to select only this:
+-------+------------+----------+
| OrgId | Name | ParentId |
+-------+------------+----------+
| 3 | Accountant | 2 |
+-------+------------+----------+
| 4 | Bookkeeper | 3 |
+-------+------------+----------+
| 5 | Controller | 2 |
+-------+------------+----------+
The entity framework select:
public virtual IList<OrgStructureModel> GetAll()
{
using (var db = _context)
{
var result = _session.GetObjectFromJson<IList<OrgStructureModel>>("OrgStructure");
if (result == null)
{
result = db.OrgStructures
.Select(org => org.ToOrgStructureModel(db.OrgStructures.Where(s => s.ParentId == org.OrgId).Count() > 0))
.ToList();
_session.SetObjectAsJson("OrgStructure", result);
}
return result;
}
}
How can this be achieved in EF?
Here's what I've tried
I've tried testing to just show child with any parent .Where(e => e.ParentId != null):
result = db.OrgStructures
.Select(org => org.ToOrgStructureModel(db.OrgStructures.Where(s => s.ParentId == org.OrgId).Count() > 0))
.Where(e => e.ParentId != null)
.ToList();
But this returned 0 results
Definition of ToOrgStructureModel:
public static OrgStructureModel ToOrgStructureModel(this OrgStructure org, bool hasChildren)
{
return new OrgStructureModel
{
OrgId = org.OrgId,
ParentId = org.ParentId,
Name = org.Name
hasChildren = hasChildren
};
}
Update:
It looks like something's wrong with the Telerik TreeList Control where the above query has data, but the control won't output the data. But the question remains, how do I get OrgId: 3,4,5 with LINQ?
Only bring back the results where the ParentId is not null.
I have two tables:
Table1 - MainTable
---------------------------------------
| MainTableID | CustomerName | BookID |
---------------------------------------
Table2 - BookTable
----------------------
| BookID | BookName |
----------------------
| 1 | physics |
----------------------
| 2 | Math |
----------------------
I want to get the result like this:
---------------------------------------
| MainTableID | CustomerName | BookID |
---------------------------------------
| 1 | Alex | Math |
---------------------------------------
I have list of BookNames in BookTable and I want to insert Data in MainTable. I am using ADO.NET entity data model in visual studio and I am doing this so:
BookTable correspondingBook=(from row in entities.BookTable
where rows.BookName == "Math"
select rows).First();
MainTable itemToAdd = new MainTable();
itemToAdd.CustomerName = "Alex";
itemToAdd.BookID = correspondingBook.BookID;
entities.MainTable.Add(itemToAdd);
entities.SaveChanges();
Is it good solution for this problem? if no, Which will be better?
I know that there are some examples but I could not apply them on my code. I am pretty new to Linq and SQL. I have two tables I want to join.
First Table:
--------------
| Id | Count |
--------------
| 1 | 10 |
--------------
| 2 | 4 |
--------------
Second Table:
--------------
| Id | Name |
--------------
| 1 | Tom |
--------------
| 2 | John |
--------------
| 3 | Nick |
--------------
| 4 | Max |
--------------
As you can see, the second table has more records than the first. My goal is to join them based on the Id. The problem is that after I have joined the tables it only displays the matching records, which is Id 1 and 2. Though I want to display every Id (from 1 to 4) and if there is no match in both tables, there should be a default value 0.
It should look like this:
----------------------
| Id | Name | Count |
----------------------
| 1 | Tom | 10 |
----------------------
| 2 | John | 4 |
----------------------
| 3 | Nick | 0 |
----------------------
| 4 | Max | 0 |
----------------------
So far I have got this code:
// first table
var listCount = entity.tblKundes.Where(x => x.Studio == 2)
.Select(x => new { x.Id, x.Name})
.GroupBy(x => x.Name).ToList();
// second table
var listBerater = entity.tblUsers.Where(x => x.Studio == 2)
.Select(x => new { x.Id, x.Name})
.ToList();
// This join should be edited so that it displays non matching records as well
var test = listCount.Join(
listBerater,
count => count.Key,
berater => berater.Id,
(count, berater) => new { listCount = count, listBerater = berater }
).ToList();
Edit:
var test2 = (from list in listCount
join berater in listBerater on list.Berater equals berater.Id into gj
from sublist in gj.DefaultIfEmpty()
select new { sublist.Id, sublist.Nachname, sublist.Vorname }).ToList();
There is a typical concept in every Structured Query Languages which is called "Left join". Left-Join means that you will have all rows of data from first table even there is no equivalent in the second one. "Inner-Join" is a little different and only looks for matched rows of data.
Here you can find enough and complete information about your issue.
Left Join
I have a sql query. I need a linq query for that.
select rightname
from IB_Right_Master
where id not in (select RightID from IB_Group_Rights where GroupID = '3');
Table : RightMaster
ID | RightName | RightGroupName |
----------------------------------------------
1 | Test | Add Group Users |
2 | Add Group | Page Access rights |
3 | Page Access | Group deletion |
3 | Delete Group | Group deletion |
----------------------------------------------
Table : Group Rights
ID | RightID | GroupID | Status |
------------------------------------------------------------
1 | 1 | 1 | True |
2 | 1 | 2 | True |
3 | 2 | 3 | True |
4 | 3 | 4 | True |
5 | 1 | 3 | True |
------------------------------------------------------------
Try this
var data = (from m in db.IB_Right_Master
where m.Id != 1
select m.RightName).ToList();
You can try this
var result = from m in db.IB_Right_Master
where IB_Group_Rights.Any(r => r.RightID != 1 && r.RightID == m.Id)
select m.RightName
Try this
var lst = IB_Right_Master.Where(x => !IB_Group_Rights.Any(y => x.id==y.RightID && y.id==1))
.Select(x => x.rightname).ToList();