我有两张桌子
CREATE TABLE RetailGroup(
Id int IDENTITY(1,1),
GroupName nvarchar(50),
)
CREATE TABLE RetailStore(
Id int IDENTITY(1,1),
StoreName nvarchar(100),
RetailGroupId int
)
RetailStore中的RetailGroupId引用RetailGroup ID。我正在尝试创建一个搜索功能,我可以搜索RetailGroup和RetailsStores。如果我得到一个匹配的RetailStore,我想要返回该组,它与所有匹配的商店记录相关联。如果我得到一个匹配的组,我想要组记录,但没有零售商店。
我尝试按以下方式进行:
public List<RetailGroup> SearchGroupsAndStores(string value)
{
return _context.RetailGroups.Where(group => group.GroupName.Contains(value)).Include(group => group.RetailStores.Where(store => store.StoreName.Contains(value))).ToList();
}
但这是错误的,因为不应该使用include来进行选择。
这是我的实体框架模型
public class RetailGroup
{
[Key]
public int Id { set; get; }
[MaxLength(50)]
public String GroupName { set; get; }
//Relations
public ICollection<RetailStore> RetailStores { set; get; }
}
这是商店的那个
public class RetailStore
{
[Key]
public int Id { get; set; }
[MaxLength(100)]
public string StoreName { get; set; }
[ForeignKey("RetailGroup")]
public int RetailGroupId { get; set; }
//Relations
public RetailGroup RetailGroup { get; set; }
public ICollection<EGPLicense> Licenses { get; set; }
}
如何创建LINQ
以获取我要查找的结果?
答案 0 :(得分:1)
使用投影返回所需结果的查询并不难:
var dbQuery = _context.RetailGroups
.Select(rg => new
{
Group = rg,
Stores = rg.RetailStores.Where(rs => rs.StoreName.Contains(value))
})
.Where(r => r.Group.GroupName.Contains(value) || r.Stores.Any());
问题是您希望结果包含在实体类中,而EF6既不支持投影到实体类型也不支持过滤包含。
要克服这些限制,可以使用AsEnumerable()
方法切换到LINQ to Objects上下文,此方法将有效地执行数据库查询,然后使用委托块从匿名类型中提取实体实例投影,将过滤后的集合绑定到它并返回它:
var result = dbQuery
.AsEnumerable()
.Select(r =>
{
r.Group.RetailStores = r.Stores.ToList();
return r.Group;
})
.ToList();
答案 1 :(得分:0)
尝试使用OR
条件过滤组名称和商店名称。
return _context.RetailGroups
.Where(group => group.GroupName.Contains(value) || group.RetailStores.Any(store => store.StoreName.Contains(value)))
.Include(group => group.RetailStores.Where(store => store.StoreName.Contains(value)))
.ToList();
另一种选择是进行2次搜索,一次针对群组,另一种针对商店。这里的问题是从两个结果中创建一组独特的组。
List<RetailGroup> retailGroups = new List<RetailGroup>();
var groupSearchResults = _context.RetailGroups
.Where(group => group.GroupName.Contains(value))
.Include(group => group.RetailStores.Where(store => store.StoreName.Contains(value)))
.ToList();
var storeSearchResults = _context.RetailStores
.Where(store => store.StoreName.Contains(value))
.Select(store => store.RetailGroup)
.ToList();
retailGroups.AddRange(groupSearchResults);
retailGroups.AddRange(storeSearchResults);
// Remove duplicates by ID
retailGroups = retailGroups
.GroupBy(group => group.Id)
.Select(group => group.First());
答案 2 :(得分:-1)
使用OR
条件并在一个语句中进行搜索:
public List<RetailGroup> SearchGroupsAndStores(string value)
{
return _context.RetailGroups
.Where(rg => rg.GroupName.Contains(value) || rg.RetailStores.Any(rs => rs.StoreName.Contains(value)))
.Include(rg => rg.RetailStores.Where(rs => rs.StoreName.Contains(value)).ToList())
.ToList();
}
或者您可以拆分搜索,先查找RetailGroups
,然后搜索RetailStores
并返回RetailGroup
:
public List<RetailGroup> SearchGroupsAndStores(string value)
{
List<RetailGroup> searchResults = new List<RetailGroup>();
searchResults.AddRange(_context.RetailGroups.Where(rg => rg.GroupName.Contains(value)).ToList());
searchResults.AddRange(_context.RetailStores.Where(rs => rs.StoreName.Contains(value)).Select(rs => rs.RetailGroup).ToList());
}