将 Double Inner Join SQl 查询转换为 LINQ
convert Double Inner Join SQl query to LINQ
我有一个 SQL 查询,想将其转换为 LINQ 语句而且我之前从未使用过 Linq 语句,请帮我解决这个问题谢谢
SELECT c.* , v.*
FROM UserEnrolleds u
INNER JOIN Courses c ON u.CourseId = c.id
INNEr JOIN Videos v ON v.CourseID = c.Id
WHERE u.UsersID = '8851d572-eaff-4a84-9ec8-aa144fecfea2'
假设变量 db 是您的数据库尝试;
var qdResult =
from u in db.UserEnrolleds
join c in db.Courses on u.CourseID equals c.id
join v in db.Videos on c.Id equals v.CourseID
where u.UsersID = '8851d572-eaff-4a84-9ec8-aa144fecfea2'
select c, v
显然您有三个 table:课程、视频和 UserEnrolled。
Courses 和 UserEnrolleds 之间存在关系,可能是一对多的关系:每个 Course 都有零个或多个 UserEnrolleds,每个 UserEnrolled 只属于一个 Course,即具有 Course.Id 的 Course外键 UserEnrolled.CourseId 指向。
同样,视频和课程之间似乎存在一对多关系:每个视频都有其所属课程的外键 Video.CourseId。
在我看来,您想要由 ID 为“8851d572-eaff...”的用户注册的课程和视频
您计划使用 UserEnrolleds - 课程 - 视频的内部联接来执行此操作。
如果您使用 Entity Framework,您可以使用两种方法。您可以使用 virtual ICollection
属性,或自己进行连接。
通常我发现 ICollection
的使用更容易,也更有吸引力,但让我们首先关注您的问题。
三个 table 上的完全内部联接
为此,我将使用 Queryable.Join
的重载之一
var result = dbContext.UserEnrolleds // get table UserEnrolleds
// keep only the UserEnrolleds with the mentioned UsersId:
.Where(userEnrolled => userEnrolled.UsersId = "8851...")
.Join(dbContext.Courses, // join with table Courses,
userEnrolled => userEnrolled.CourseId, // from every userEnrolled take the CourseId
course => course.Id, // from every course take the Id
(userEnrolled, Course) => new // remember the matching items for the next join
{
UserEnrolled = userEnrolled,
Course = Course,
})
.Join(dbContext.Videos, // join with the Videos table
joinResult => joinResult.Course.Id, // from the previous Join take the Course Id
video => video.CourseId, // from the video take the CourseId
(joinResult, video) => new // when they match, make one new object
{
UserEnrolled => joinResult.UserEnrolled,
Course => joinResult.Course,
Video => video,
})
加入后,使用 Select 仅查询您实际计划使用的属性。
.Select(joinResult => new
{
Course = new
{
Id = joinResult.Course.Id,
Name = joinResult.Course.Name,
...
},
Video = new
{
Id = joinResult.Video.Id,
Name = joinResult.Video.Name,
...
}
UserEnrolled = ...
});
如果要查询完整的课程和视频:
.Select(joinResult => new
{
Course = joinResult.Course,
Video = joinResult.Video,
})
请注意,您将转移几个您可能不会使用的属性,尤其是外键。
当然,您可以在联接的最后一个参数中执行 select(结果Select 或)。我没有这样做,为了更容易理解。
使用虚拟 ICollection
很多时候,如果您有一对多关系,您想要执行 GroupJoin 而不是 Join:您想要所有 "Courses with their Videos".
所以不是 table:
Course 1 - Video 10
Course 1 - Video 11
Course 1 - Video 12
Course 2 - Video 13
Course 2 - Video 14
Course 3 - Video 15
你想要一个 table:
Course 1 with its Videos 10, 11, and 12
Course 2 with its Videos 13, and 14
Course 3 with its one and only Video 15
Course 4 has no Video at all.
如果您更喜欢 "Courses with their Videos"(也许还有一些与 UserEnrolleds 相关的东西),使用 virtual ICollection
比自己进行连接要容易得多。
如果您遵循了 entity framework code first conventions,您将 类 类似于以下内容:
class Course
{
public int Id {get; set;}
public string Name {get; set;}
...
// Every Course has zero or more Videos:
public virtual ICollection<Video> Videos {get; set;}
// Every Course has zero or more UserEnrolleds:
public virtual ICollection<UserEnrolled> UserEnrolleds {get; set;}
}
public class Video
{
public int Id {get; set;}
public string Name {get; set;}
...
// every Video belongs to exactly one Course, using foreign key:
public int CourseId {get; set;}
public virtual Course Course {get; set;}
}
UserEnrolled 与视频相似:
public class UserEnrolled
{
public int Id {get; set;}
public string UsersId {get; set;}
...
// every Video belongs to exactly one Course, using foreign key:
public int CourseId {get; set;}
public virtual Course Course {get; set;}
}
In entity framework the columns of the tables are represented by the non-virtual properties. The virtual properties represent the relations between the tables (one-to-many, many-to-many, ...)
外键是您 table 中的真实列,因此它们是非虚拟的
为了完整起见,DbContext:
class MyDbContext : DbContext
{
public DbSet<Course> Courses {get; set;}
public DbSet<Video> Videos {get; set;}
public DbSet<UserEnrolled> UserEnrolleds {get; set;}
}
这就是 entity framework 检测您的 table、table 中的列以及它们之间的关系所需知道的全部内容。它还将为您创建和使用主键和外键。
现在获取所有课程,每个课程都有他们的视频,这些课程由 ID 为“8851d572-eaff...”的用户注册(=至少有一个 UserEnrolled 的 UsersId 等于“8851d572-eaff. .."),使用以下查询:
var coursesAndVideosEnrolledByUser = dbContext.Courses
// keep only the Courses that are enrolled by user with Id "8851..."
.Where(course => course.UserEnrolleds
.Any(userEnrolled => userEnrolled.UsersId = "8851d572-eaff..."))
.Select(course => new
{
Id = course.Id,
Name = course.Name,
...
Videos = course.Videos,
});
您是否同意,如果您想获得由特定用户参加的课程,每个课程都有他们的视频,这看起来会更自然吗?
奖励点:如果此用户参加的课程没有视频,您仍然会在结果中找到它们。您不会使用内部联接获取它们!
我有一个 SQL 查询,想将其转换为 LINQ 语句而且我之前从未使用过 Linq 语句,请帮我解决这个问题谢谢
SELECT c.* , v.*
FROM UserEnrolleds u
INNER JOIN Courses c ON u.CourseId = c.id
INNEr JOIN Videos v ON v.CourseID = c.Id
WHERE u.UsersID = '8851d572-eaff-4a84-9ec8-aa144fecfea2'
假设变量 db 是您的数据库尝试;
var qdResult =
from u in db.UserEnrolleds
join c in db.Courses on u.CourseID equals c.id
join v in db.Videos on c.Id equals v.CourseID
where u.UsersID = '8851d572-eaff-4a84-9ec8-aa144fecfea2'
select c, v
显然您有三个 table:课程、视频和 UserEnrolled。
Courses 和 UserEnrolleds 之间存在关系,可能是一对多的关系:每个 Course 都有零个或多个 UserEnrolleds,每个 UserEnrolled 只属于一个 Course,即具有 Course.Id 的 Course外键 UserEnrolled.CourseId 指向。
同样,视频和课程之间似乎存在一对多关系:每个视频都有其所属课程的外键 Video.CourseId。
在我看来,您想要由 ID 为“8851d572-eaff...”的用户注册的课程和视频
您计划使用 UserEnrolleds - 课程 - 视频的内部联接来执行此操作。
如果您使用 Entity Framework,您可以使用两种方法。您可以使用 virtual ICollection
属性,或自己进行连接。
通常我发现 ICollection
的使用更容易,也更有吸引力,但让我们首先关注您的问题。
三个 table 上的完全内部联接
为此,我将使用 Queryable.Join
的重载之一var result = dbContext.UserEnrolleds // get table UserEnrolleds
// keep only the UserEnrolleds with the mentioned UsersId:
.Where(userEnrolled => userEnrolled.UsersId = "8851...")
.Join(dbContext.Courses, // join with table Courses,
userEnrolled => userEnrolled.CourseId, // from every userEnrolled take the CourseId
course => course.Id, // from every course take the Id
(userEnrolled, Course) => new // remember the matching items for the next join
{
UserEnrolled = userEnrolled,
Course = Course,
})
.Join(dbContext.Videos, // join with the Videos table
joinResult => joinResult.Course.Id, // from the previous Join take the Course Id
video => video.CourseId, // from the video take the CourseId
(joinResult, video) => new // when they match, make one new object
{
UserEnrolled => joinResult.UserEnrolled,
Course => joinResult.Course,
Video => video,
})
加入后,使用 Select 仅查询您实际计划使用的属性。
.Select(joinResult => new
{
Course = new
{
Id = joinResult.Course.Id,
Name = joinResult.Course.Name,
...
},
Video = new
{
Id = joinResult.Video.Id,
Name = joinResult.Video.Name,
...
}
UserEnrolled = ...
});
如果要查询完整的课程和视频:
.Select(joinResult => new
{
Course = joinResult.Course,
Video = joinResult.Video,
})
请注意,您将转移几个您可能不会使用的属性,尤其是外键。
当然,您可以在联接的最后一个参数中执行 select(结果Select 或)。我没有这样做,为了更容易理解。
使用虚拟 ICollection
很多时候,如果您有一对多关系,您想要执行 GroupJoin 而不是 Join:您想要所有 "Courses with their Videos".
所以不是 table:
Course 1 - Video 10
Course 1 - Video 11
Course 1 - Video 12
Course 2 - Video 13
Course 2 - Video 14
Course 3 - Video 15
你想要一个 table:
Course 1 with its Videos 10, 11, and 12
Course 2 with its Videos 13, and 14
Course 3 with its one and only Video 15
Course 4 has no Video at all.
如果您更喜欢 "Courses with their Videos"(也许还有一些与 UserEnrolleds 相关的东西),使用 virtual ICollection
比自己进行连接要容易得多。
如果您遵循了 entity framework code first conventions,您将 类 类似于以下内容:
class Course
{
public int Id {get; set;}
public string Name {get; set;}
...
// Every Course has zero or more Videos:
public virtual ICollection<Video> Videos {get; set;}
// Every Course has zero or more UserEnrolleds:
public virtual ICollection<UserEnrolled> UserEnrolleds {get; set;}
}
public class Video
{
public int Id {get; set;}
public string Name {get; set;}
...
// every Video belongs to exactly one Course, using foreign key:
public int CourseId {get; set;}
public virtual Course Course {get; set;}
}
UserEnrolled 与视频相似:
public class UserEnrolled
{
public int Id {get; set;}
public string UsersId {get; set;}
...
// every Video belongs to exactly one Course, using foreign key:
public int CourseId {get; set;}
public virtual Course Course {get; set;}
}
In entity framework the columns of the tables are represented by the non-virtual properties. The virtual properties represent the relations between the tables (one-to-many, many-to-many, ...)
外键是您 table 中的真实列,因此它们是非虚拟的
为了完整起见,DbContext:
class MyDbContext : DbContext
{
public DbSet<Course> Courses {get; set;}
public DbSet<Video> Videos {get; set;}
public DbSet<UserEnrolled> UserEnrolleds {get; set;}
}
这就是 entity framework 检测您的 table、table 中的列以及它们之间的关系所需知道的全部内容。它还将为您创建和使用主键和外键。
现在获取所有课程,每个课程都有他们的视频,这些课程由 ID 为“8851d572-eaff...”的用户注册(=至少有一个 UserEnrolled 的 UsersId 等于“8851d572-eaff. .."),使用以下查询:
var coursesAndVideosEnrolledByUser = dbContext.Courses
// keep only the Courses that are enrolled by user with Id "8851..."
.Where(course => course.UserEnrolleds
.Any(userEnrolled => userEnrolled.UsersId = "8851d572-eaff..."))
.Select(course => new
{
Id = course.Id,
Name = course.Name,
...
Videos = course.Videos,
});
您是否同意,如果您想获得由特定用户参加的课程,每个课程都有他们的视频,这看起来会更自然吗?
奖励点:如果此用户参加的课程没有视频,您仍然会在结果中找到它们。您不会使用内部联接获取它们!