我正在尝试将此SQL查询转换为存储库中的LINQ:
SELECT
ministry.Id, ministry.Name as ministry,
MemberGroup.Name as memberGroup
FROM
Ministry, MemberGroup
WHERE
ministry.Id = MemberGroup.MinistryId;
我的Linq尝试:
var ministries = await _context.Ministries
.Join(_context.MemberGroups, d => d.Id, f => f.MinistryId, (d, f) => d)
.ToList();
return ministries;
答案 0 :(得分:0)
要回答此问题,我们需要查看您的Ministry和MemberGroup之间的关系如何。像EF这样的ORM的要点和功能是将其设置为了解表之间的关系,并使其自动管理联接。
例如:如果部委引用单个会员组,以在部委和会员组之间形成一对一或多对一的关系,则您可能具有类似于以下的实体结构:
(多对1)
public class Ministry
{
public int MinistryId { get; set; }
public string Name { get; set; }
public virtual MemberGroup MemberGroup { get; set; }
}
public class MemberGroup
{
public int MemberGroupId { get; set; }
public string Name { get; set; }
}
在映射时可以使用
设置部(EF 6)
.HasRequired(x => x.MemberGroup).WithMany().Map(x => x.MapKey("MemberGroupId")
(EF核心)
.HasOne(x => x.MemberGroup).WithMany().HasForeignKey("MemberGroupId")
...然后,用于检索详细信息的查询将类似于:
public class MinistryViewModel
{
public int MinistryId { get; set; }
public string Ministry { get; set; }
public string MemberGroup { get; set; }
}
var ministries = _context.Ministries
.Select(x => new MinistryViewModel
{
MinistryId = x.MinistryId,
Ministry = x.Name,
MemberGroup = x.MemberGroup.Name
}).ToList();
您的示例中的要点:
.Select()
可以填充匿名类型,但是不能(或不应)从函数中返回这些匿名类型。创建一个视图模型/ DTO,以获取要返回的数据的详细信息。不应鼓励从方法返回的实体以及从其装入的上下文之外的实体。这很容易导致错误,性能问题和安全性问题。
await
/ async
:
var ministries =等待_context.Ministries
.Select(x => new MinistryViewModel
{
MinistryId = x.MinistryId,
Ministry = x.Name,
MemberGroup = x.MemberGroup.Name
}).ToListAsync();
...将它们定位于长时间运行的查询,但最好将简单的快速查询留作同步调用。
答案 1 :(得分:0)
可惜的是,您没有给我们您的类和查询的要求,而是给了我们一些SQL语句,我们必须从中猜测您的类以及类之间的关系。
在我看来,您有一个表Ministries
,其中每个Ministry
至少具有属性Id
和Name
。您还有一个表MemberGroups
,每个MemberGroup
都有一个Id
,Name
和一个外键MemberGroupId
。
在我看来Ministries
和MemberGroups
之间存在一对多的关系:每个Ministry
都具有零个或多个MemberGroups
,每个{{1 }}恰好属于一个MemberGroup
,这是外键指向的部。
可能一对多是相反的。或这是一对一的关系。这就是为什么我想要一个要求。如果是相反的话,答案将是相似的,但是您将获得要点。
如果您遵循Entity Framework Code first conventions,则将具有类似的课程:
Ministry
这是实体框架检测表,列和表之间的关系所需要知道的全部内容。仅当您想要偏离默认行为时,才需要属性或流畅的API
在实体框架中,表的列由非虚拟属性表示。虚拟属性表示表之间的关系(一对多,多对多)
如果您遵循约定,则查询将非常简单直观:
要求:为我提供所有(或某些)政府部门的ID和名称(可能还有其他属性),每个都具有其MemberGroups的名称(可能还有其他属性)< / p>
class Ministry
{
public int Id {get; set;}
public string Name {get; set;}
// every Ministry has zero or more MemberGroups (one-to-many)
public virtual ICollection<MemberGroup> MemberGroups {get; set;}
}
class MemberGroup
{
public int Id {get; set;}
public string Name {get; set;}
// every MemberGroup belongs to exactly one Ministry, using foreign key
public int MinistryId {get; set;}
public virtual Ministry Ministry {get; set;}
}
public MyDbContext : DbContext
{
public DbSet<Ministry> Ministries {get; set;}
public DbSet<MemberGroup> MemberGroups {get; set;}
}
实体框架知道您的一对多关系,并且足够聪明,可以检测到为此而需要(组)联接。
顺便说一句,如果您只需要memberGroups的名称:
var result = dbContext.Ministries
.Where(ministry => ...) // only if you don't want all Ministries
.Select(ministry => new
{
// Select only the properties that you plan to use
Id = ministry.Id,
Name = ministry.Name,
...
MemberGroups = ministry.MemberGroups
.Where(memberGroup => ...) // only if you don't want all its MemberGroups
.Select(memberGroup => new
{
// again: only the properties that you plan to use
Id = memberGroup.Id,
Name = memberGroup.Name,
...
// not needed: you know the value
// MinistryId = memberGroup.MinistryId,
})
.ToList(),
});
如果您真的想自己加入GroupJoin:
...
MemberGroupNames = ministry.MemberGroups
.Select(memberGroup => memberGroup.Name)
.ToList(),
最后:如果您不希望各部委将其MemberGroups作为GroupJoin,而作为简单的联接,请使用SelectMany代替Select,或者使用Join代替GroupJoin:
var result = dbContext.Ministries.GroupJoin(
dbContext.MemberGroup,
ministry => ministry.Id,
memberGroup => memberGroup.MinistryId,
(ministry, memberGroupsOfThisMinistry) => new
{
Id = ministry.Id,
Name = ministry.Name,
MemberGroups = memberGroupsOfThisMinistry.Select(memberGroup => new
{
Id = memberGroup.Id,
Name = memberGroup.Name,
...
})
.ToList(),
});