我有一个 ASP.NET Core 项目,其中使用实体框架来管理数据库查询。我想知道如何使用实体框架在两个表之间执行
INNER JOIN
,在本例中是 user
表与 type_access_user
表。我想在用户进行的查询中返回 type_access_user
的名称。
我是 C# 和实体框架新手,我需要这方面的帮助。
public class Type_access_user
{
[Key]
public int id { get; set; }
public string? name { get; set; }
public DateTime createdAt { get; set; }
public DateTime updatedAt { get; set; }
}
public class User
{
[Key]
public int id { get; set; }
public string? uid { get; set; }
public int? type_access_user_id { get; set; }
}
返回数据的代码:
return await _context.User
.Select(user => new User
{
id = user.id,
uid = user.uid,
type_access_user_id = user.type_access_user_id,
createdAt = user.createdAt,
updatedAt = user.updatedAt,
}).ToListAsync();
我需要类似于此 SQL 查询的内容:
SELECT
us.id, us.uid, us.type_access_user_id,
tyac.name AS type_access_user_name,
us.createdAt, us.updatedAt
FROM
User AS us
INNER JOIN
Type_access_user AS tyac ON tyac.id = us.type_access_user_id
我如何使用实体在两个表之间进行 INNER JOIN,在此 如果用户表带有 type_access_user,我想返回 在用户中进行的查询中 type_access_user 的名称。
根据您的场景,为了使用实体框架在两个表(User 和 TypeAccessUser)之间执行内部联接并在
TypeAccessUser
上进行的查询中返回 User
名称,我们根据您的共享代码有两种方法片段。
首先,您可以将 TSQL 转换为相关的 Linq 查询,保持 POCO 类不变。
另一种是使用 Navigation 属性,然后使用 Include 方法进行预加载并使用 Select 语句投影结果。在这种情况下,您可能需要使用实体框架中的 navigation 属性修改类结构。
方式:1:
演示模型:
public class TypeAccessUser
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
public class User
{
public int Id { get; set; }
public string Uid { get; set; }
public int? TypeAccessUserId { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
带有示例数据的演示控制器:
public IActionResult Index()
{
var typeAccessUsers = new List<TypeAccessUser>
{
new TypeAccessUser { Id = 1, Name = "Admin", CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now },
new TypeAccessUser { Id = 2, Name = "User", CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now }
};
var users = new List<User>
{
new User { Id = 1, Uid = "user1", TypeAccessUserId = 1, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now },
new User { Id = 2, Uid = "user2", TypeAccessUserId = 2, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now }
};
var result = from user in users
join typeAccessUser in typeAccessUsers on user.TypeAccessUserId equals typeAccessUser.Id
select new
{
UserId = user.Id,
UserUid = user.Uid,
TypeAccessUserId = user.TypeAccessUserId,
TypeAccessUserName = typeAccessUser.Name,
CreatedAt = user.CreatedAt,
UpdatedAt = user.UpdatedAt
};
return View(result);
}
您可以注意到 join 子句指定两个集合的连接。它将每个用户对象与一个
typeAccessUser
对象相匹配,其中 user.TypeAccessUserId
等于 typeAccessUser.Id.
这相当于 SQL INNER JOIN
操作,确保结果中仅包含两个集合中具有匹配键的记录。
查看:
@model IEnumerable<dynamic>
<h1>User List</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>User ID</th>
<th>UID</th>
<th>Type Access User ID</th>
<th>Type Access User Name</th>
<th>Created At</th>
<th>Updated At</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@item.UserId</td>
<td>@item.UserUid</td>
<td>@item.TypeAccessUserId</td>
<td>@item.TypeAccessUserName</td>
<td>@item.CreatedAt</td>
<td>@item.UpdatedAt</td>
</tr>
}
</tbody>
</table>
输出:
方式:2
如前所述,如果您想在该场景中使用实体框架导航,您需要修改您的类,如下所示:
public class TypeAccessUser
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public ICollection<User> Users { get; set; }
}
public class User
{
[Key]
public int Id { get; set; }
public string Uid { get; set; }
public int? TypeAccessUserId { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
[ForeignKey("TypeAccessUserId")]
public TypeAccessUser TypeAccessUser { get; set; }
}
如果您使用上述类装饰,那么您可以使用 Include 以便从导航表加载相关数据,在您的场景中,导航表为
User
表。
相关查询:
public async Task<IActionResult> Index()
{
var result = await _context.Users
.Include(user => user.TypeAccessUser)
.Select(user => new
{
user.Id,
user.Uid,
user.TypeAccessUserId,
TypeAccessUserName = user.TypeAccessUser.Name,
user.CreatedAt,
user.UpdatedAt
})
.ToListAsync();
return View(result);
}