可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I need a help,
I have two dataTable called A and B , i need all rows from A and matching row of B
Ex:
A: B:
User | age| Data ID | age|Growth
1 |2 |43.5 1 |2 |46.5
2 |3 |44.5 1 |5 |49.5
3 |4 |45.6 1 |6 |48.5
I need Out Put:
User | age| Data |Growth
------------------------
1 |2 |43.5 |46.5
2 |3 |44.5 |
3 |4 |45.6 |
回答1:
The example data and output you've provided does not demonstrate a left join. If it was a left join your output would look like this (notice how we have 3 results for user 1, i.e. once for each Growth record that user 1 has):
User | age| Data |Growth
------------------------
1 |2 |43.5 |46.5
1 |2 |43.5 |49.5
1 |2 |43.5 |48.5
2 |3 |44.5 |
3 |4 |45.6 |
Assuming that you still require a left join; here's how you do a left join in Linq:
var results = from data in userData
join growth in userGrowth
on data.User equals growth.User into joined
from j in joined.DefaultIfEmpty()
select new
{
UserData = data,
UserGrowth = j
};
If you want to do a right join, just swap the tables that you're selecting from over, like so:
var results = from growth in userGrowth
join data in userData
on growth.User equals data.User into joined
from j in joined.DefaultIfEmpty()
select new
{
UserData = j,
UserGrowth = growth
};
The important part of the code is the into statement, followed by the DefaultIfEmpty. This tells Linq that we want to have the default value (i.e. null) if there isn't a matching result in the other table.
回答2:
Doctor Jones showed left outer join, but correct answer would be slightly different - because in the original question two tables linked on age field so to get result exactly as needed following code should be used.
....
//ctx = dataContext class - not shown here.
var user1 = new UserData() { User = 1, Age = 2, Data = 43.5 };
var user2 = new UserData() { User = 2, Age = 3, Data = 44.5 };
var user3 = new UserData() { User = 3, Age = 4, Data = 45.6 };
ctx.UserData.AddRange(new List<UserData> { user1, user2, user3 });
var growth1 = new UserGrowth() { Id = 1, Age = 2, Growth = 46.5 };
var growth2 = new UserGrowth() { Id = 1, Age = 5, Growth = 49.5 };
var growth3 = new UserGrowth() { Id = 1, Age = 6, Growth = 48.5 };
ctx.UserGrowth.AddRange(new List<UserGrowth> { growth1, growth2, growth3 });
var query = from userData in ctx.UserData
join userGrowth in ctx.UserGrowth on userData.Age equals userGrowth.Age
into joinGroup
from gr in joinGroup.DefaultIfEmpty()
select new
{
User = userData.User,
age = userData.Age,
Data = (double?)userData.Data,
Growth = (double?)gr.Growth
};
Console.WriteLine("{0} | {1} | {2} | {3}", "User", "age", "Data", "Growth");
foreach (var x in query)
{
Console.WriteLine("{0} | {1} | {2} | {3}", x.User, x.age, x.Data, x.Growth);
}
.... with following entity classes:
public class UserData
{
[Key]
public int User { get; set; }
public int Age { get; set; }
public double Data { get; set; }
}
public class UserGrowth
{
public int Id { get; set; }
public int Age { get; set; }
public double Growth { get; set; }
}
回答3:
Easy way is to use Let keyword. This works for me.
from AItem in Db.A
Let BItem = Db.B.Where(x => x.id == AItem.id ).FirstOrDefault()
Where SomeCondition
Select new YourViewModel
{
X1 = AItem.a,
X2 = AItem.b,
X3 = BItem.c
}
This is a simulation of Left Join. If each item in B table not match to A item , BItem return null
回答4:
Simple Example
Model
class Employee
{
public string Name { get; set; }
public int ID { get; set; }
public int ProjectID { get; set; }
}
class Project
{
public int ProjectID { get; set; }
public string ProjectName { get; set; }
}
Methord
public void leftrighjoin(){
Project P1 = new Project() { ProjectID = 1, ProjectName = "UID" };
Project P2 = new Project() { ProjectID = 2, ProjectName = "RBS" };
Project P3 = new Project() { ProjectID = 3, ProjectName = "XYZ" };
// Employee List
List<Employee> ListOfEmployees = new List<Employee>();
ListOfEmployees.AddRange((new Employee[]
{
new Employee() { ID = 1, Name = "Sunil", ProjectID = 1 },
new Employee() { ID = 1, Name = "Anil", ProjectID = 1 },
new Employee() { ID = 1, Name = "Suman", ProjectID = 2 },
new Employee() { ID = 1, Name = "Ajay", ProjectID = 3 },
new Employee() { ID = 1, Name = "Jimmy", ProjectID = 4 }}));
//Project List
List<Project> ListOfProject = new List<Project>();
ListOfProject.AddRange(new Project[] { P1, P2, P3 });
//Left join
var Ljoin = from emp in ListOfEmployees
join proj in ListOfProject
on emp.ProjectID equals proj.ProjectID into JoinedEmpDept
from proj in JoinedEmpDept.DefaultIfEmpty()
select new
{
EmployeeName = emp.Name,
ProjectName = proj != null ? proj.ProjectName : null
};
//Right outer join
var RJoin = from proj in ListOfProject
join employee in ListOfEmployees
on proj.ProjectID equals employee.ProjectID into joinDeptEmp
from employee in joinDeptEmp.DefaultIfEmpty()
select new
{
EmployeeName = employee != null ? employee.Name : null,
ProjectName = proj.ProjectName
};
//Printing result of left join
Console.WriteLine(string.Join("\n", Ljoin.Select(emp => " Employee Name = " +
emp.EmployeeName + ", Project Name = " + emp.ProjectName).ToArray<string>()));
//printing result of right outer join
Console.WriteLine(string.Join("\n", RJoin.Select(emp => " Employee Name = " +
emp.EmployeeName + ", Project Name = " + emp.ProjectName).ToArray<string>()));
}