我有一个我正在研究的linqpad脚本并且它可以工作,但问题是它使用.AsEnumerable()
将集合调用到内存中。有一天可能会有成千上万的这些,所以我想尽可能地推迟一切。
我正在尝试简单地执行检查,以确保我是否将new long[] { 2, 4 }
传递给该功能,然后是两者 ID为2和4的任何体验将被退回。
以前,我只使用.Contains()
,但这会返回 2或4的体验。
是否有更好的方法来编写此代码,以便它返回IQueryable<Experience>
而不是List<Experience>
,因此我不必将所有结果加载到内存中以执行字符串连接?
void Main()
{
var AllExperiences = new List<_Experience>();
AllExperiences.Add(new _Experience { Id = 1, Name = "Experience 1" });
AllExperiences.Add(new _Experience { Id = 2, Name = "Experience 2" });
AllExperienceTags.Add(new _ExperienceTag { ExperienceId = 1, TagId = 2 });
AllExperienceTags.Add(new _ExperienceTag { ExperienceId = 1, TagId = 4 });
AllExperienceTags.Add(new _ExperienceTag { ExperienceId = 2, TagId = 2 });
var experiences = FilterBySelectedTags(AllExperiences, new[] { 2, 4 }.ToList());
experiences.Dump();
}
public List<_ExperienceTag> AllExperienceTags = new List<UserQuery._ExperienceTag>();
// Define other methods and classes here
public List<_Experience> FilterBySelectedTags(List<_Experience> experiences, List<int> selectedTagIds)
{
var filteredExperiencesTags = AllExperienceTags.Where(x => selectedTagIds.Contains(x.TagId));
var obj = filteredExperiencesTags.OrderBy(x => x.TagId).GroupBy(x => x.ExperienceId).AsEnumerable().Select(x => new
{
ExperienceId = x.Key,
ExpTags = string.Join(", ", x.Select(y => y.TagId))
});
var filteredTags = obj.Where(x => x.ExpTags == string.Join(", ", selectedTagIds));
// make sure all the selected tags are found in the experience, not just any
return experiences.Where(x => filteredTags.Select(y => y.ExperienceId).Contains(x.Id)).ToList();
}
public class _Experience
{
public int Id { get; set; }
public string Name { get; set; }
}
public class _ExperienceTag
{
public int ExperienceId { get; set; }
public int TagId { get; set; }
}
答案 0 :(得分:3)
Experience
实体应具有ExperienceTags
的导航属性:
public virtual ICollection<ExperienceTag> ExperienceTags{get;set;}
如果是这种情况,这应该有效:
var query= from e in Experiences
let experienceTagIds=e.ExperiencesTags.Select(et=>et.TagId)
where selectedTagIds.All(x=>experienceTagIds.Contains(x))
select e;
答案 1 :(得分:1)
假设有经验,上面有导航属性标签,那么你可以这样做:
void Main()
{
var experiences = Experiences.FilterBySelectedTags(new long[] { 2, 4 });
experiences.Dump();
}
public static class ExperienceExtensions {
public static IQueryable<Experience> FilterBySelectedTags(this IQueryable<Experience> experiences, IEnumerable<long> selectedTagIds)
{
return experiences.Where(e=>selectedTagIds.All(id=>e.Tags.Any(t=>t.TagId==id)));
}
}