C# 林:帮我把这件事做好

C# 林:帮我把这件事做好,c#,.net,entity-framework,linq,C#,.net,Entity Framework,Linq,我有以下专栏: PersonId CategoryId SubCategoryId 1 61 47 2 61 48 3 61 0 424 4 61 0 425 5 84 55 6 61

我有以下专栏:

    PersonId   CategoryId   SubCategoryId
1      61           47          
2      61           48          
3      61           0           424
4      61           0           425
5      84           55          
6      61                       585
7      101          48          
8      101                      424
8      666          47          
10     666                      424
当我只搜索categoryId时,它是fine,subCategoryId时,它是fine,但当我同时搜索这两个时,比如categoryId=47&&subCategoryId=424。 我不能让它工作。。。在这种情况下,我只需要61人和666人

我可以用foreach,但这不是一个好主意

你们能帮我吗

if (ids.IdCategory != null && ids.IdSubCategory != null)
{
    query = unitOfWork.PersonSkillsRepository.GetAll().Where(m => m.IdCategory == ids.IdCategory || m.IdSubCategory == ids.IdSubCategory);
}
else if (ids.IdCategory != null)
    query = unitOfWork.PersonSkillsRepository.GetAll().Where(m => m.IdCategory == ids.IdCategory);
else
    query = unitOfWork.PersonSkillsRepository.GetAll().Where(m => m.IdSubCategory == ids.IdSubCategory);
第一种情况是我得到了我想要的一半。。。但我想用一些方法来过滤,因为这样我也得到了101,我不知道如何查看人们是否同时拥有类别和子类别

我看不出一个没有foreach的方法能做到这一点

entities.Where(z => z.categoryId == 47 || z.subCategoryId == 424)
    .GroupBy(z => z.personId)
    .Where(z => z.Count() == 2)
    .SelectMany(z => z.ToList());
可能会为您提供所需的数据

该查询表示“过滤数据并仅返回
categoryId
为47
=424”的数据”。然后将它们分组,并检查其中是否有两行(即一行用于
类别ID
,一行用于
子类别ID
)。

问题是在SubCategoryId列中,CategoryId=47没有任何值,这就是为什么当您同时搜索这两个字段时,不会给出任何结果。 尝试在CategoryId=47的子类别ID中添加任何值…

编辑:

问题进一步澄清后,下面的代码应该可以工作

        if (ids.IdCategory != null && ids.IdSubCategory != null)
        {
            query = unitOfWork.PersonSkillsRepository.GetAll().Where(m => (m.IdCategory == ids.IdCategory || m.IdSubCategory == ids.IdSubCategory) && m.IdPerson != 101);
        }
首先,对于搜索条件,您的数据将返回null。下面是linq的一些示例,可能有助于此场景

你可以做不同种类的linq

    List<CollectionObject> ColObj = CollectionObject.GetListCollectionObj();

    List<CollectionObject> LinqResult = ColObj.Where(x => x.CategoryID == 47 && x.SubcategoryID == null).ToList();
List ColObj=CollectionObject.getListCollectionObject();
List LinqResult=ColObj.Where(x=>x.CategoryID==47&&x.SubcategoryID==null).ToList();
下面的代码可以很好地处理上面的linq语句

    class CollectionObject
    {
        public int PersonID { get; set; }
        public int? CategoryID { get; set; }
        public int? SubcategoryID { get; set; }

    public static List<CollectionObject> GetListCollectionObj()
    {
        List<CollectionObject> LColObj = new List<CollectionObject>();

        LColObj.Add(new CollectionObject() { PersonID = 61, CategoryID = 47, SubcategoryID = null });
        LColObj.Add(new CollectionObject() { PersonID = 61, CategoryID = 48, SubcategoryID = null });
        LColObj.Add(new CollectionObject() { PersonID = 61, CategoryID = 0, SubcategoryID = 424 });
        LColObj.Add(new CollectionObject() { PersonID = 61, CategoryID = 0, SubcategoryID = 425 });
        LColObj.Add(new CollectionObject() { PersonID = 101, CategoryID = 48, SubcategoryID = null });
        LColObj.Add(new CollectionObject() { PersonID = 101, CategoryID = null, SubcategoryID = 424 });
        LColObj.Add(new CollectionObject() { PersonID = 666, CategoryID = 47, SubcategoryID = null });
        LColObj.Add(new CollectionObject() { PersonID = 666, CategoryID = null, SubcategoryID = 424 });            

        return LColObj;
    }
}
类集合对象
{
公共int PersonID{get;set;}
公共int?CategoryID{get;set;}
公共int?子类别id{get;set;}
公共静态列表GetListCollectionObj()
{
List LColObj=新列表();
添加(新的CollectionObject(){PersonID=61,CategoryID=47,SubcategoryID=null});
添加(新的CollectionObject(){PersonID=61,CategoryID=48,SubcategoryID=null});
添加(新的CollectionObject(){PersonID=61,CategoryID=0,SubcategoryID=424});
添加(新的CollectionObject(){PersonID=61,CategoryID=0,SubcategoryID=425});
添加(新的CollectionObject(){PersonID=101,CategoryID=48,SubcategoryID=null});
添加(新的CollectionObject(){PersonID=101,CategoryID=null,SubcategoryID=424});
添加(新的CollectionObject(){PersonID=666,CategoryID=47,SubcategoryID=null});
添加(新的CollectionObject(){PersonID=666,CategoryID=null,SubcategoryID=424});
返回LColObj;
}
}

您应该按人员id对所有人员技能进行分组,然后仅选择包含给定类别和子类别的组:

unitOfWork.PersonSkillsRepository.GetAll()
          .GroupBy(p => p.PersonId)
          .Where(g => g.Any(p => p.IdCategory == ids.IdCategory) 
                   && g.Any(p => p.IdSubCategory == ids.IdSubCategory))
          .Select(g => g.Key)
对于优化,您可以在分组之前筛选出与任何给定类别不匹配的技能

unitOfWork.PersonSkillsRepository.GetAll()
          .Where(p => p.IdCategory == ids.IdCategory 
                   || p.IdSubCategory == ids.IdSubCategory)
          .GroupBy(p => p.PersonId)
          .Where(g => g.Any(p => p.IdCategory == ids.IdCategory) 
                   && g.Any(p => p.IdSubCategory == ids.IdSubCategory))
          .Select(g => g.Key) 

下面的方法可以,但是您应该知道您存储数据的方式非常奇怪

(我的意思是,您的所有子类别不是都与一个类别相关吗?)


链接。

好吧,当我在做我的工作时,似乎有3个人想出了同样的主意,所以我将把我的也加入进来——加上OP需要的关键补充

Func<IGrouping<int, CollectionObject>, bool> query  = 
        gp=>
              gp.Any(g=>g.CategoryID == 47) && 
              gp.Any(g=>g.SubcategoryID == 424);

var q = (from p in ColObj
        group p by p.PersonID)
        .Where(query);
Func查询=
gp=>
gp.Any(g=>g.CategoryID==47)和
gp.Any(g=>g.Subcategory ID==424);
var q=(从ColObj中的p开始)
p组由p.PersonID创建)
.何处(查询);

有时,您需要将
query
替换为单字段版本。

请提供一些您尝试过的代码。在您不太乱的情况下,Linq的性能与foreach循环一样好。在内部,它也会迭代IEnumerable。有很多网站都是这样工作的——你给出一些要求,然后有人为你实现这些要求(可能是为了一些钱)。但是StackOverflow以不同的方式工作-您尝试自己实现需求,如果您有一些问题(错误或意外结果),那么您可以给出问题描述,您当前的代码并请他人帮助您。这是因为您的示例中没有匹配行,
categoryId=47&&subCategoryId=424
我编辑了我的帖子。我这样做了,101也来了,我想要两个问题是的,我的问题人。。。我正在尝试一种方法101不来太多,过滤器在某种程度上,集团。。。我不知道如果一行同时有47和424,那么它就不会包含在这个查询中。这是真的@Magnus。根据他的样本数据,这似乎不是一个可能的情况,但谢谢你提出它。@Magnus是的。。。。以前是这样的,但这次改变不是我的。。从我的老板那里得知,这个问题被标记为实体框架,“优化”可能只会使生成的查询复杂化,而不会带来任何性能提升。@Magnus取决于
GetAll()
返回类型。通常它是一个已经从数据库中获取的
IEnumerable
。分组前过滤掉大部分记录将加快分组速度并节省一些内存,同时检查
g。Any
为O(N),这将随着组大小的增加而增加高返回类型iqeryable如果它是
iqeryable
,“优化”将不会带来性能增益(甚至可能做相反的事情)。但是对于IEnumerable,我同意你的说法。@AntonioHenrique是的,如果是
IQueryable
使用@Magnus建议的第一个版本。但请记住,公开
IQueryable
通常会将数据访问逻辑扩展到应用程序上,并导致代码重复(不同位置的相同查询)
Func<IGrouping<int, CollectionObject>, bool> query  = 
        gp=>
              gp.Any(g=>g.CategoryID == 47) && 
              gp.Any(g=>g.SubcategoryID == 424);

var q = (from p in ColObj
        group p by p.PersonID)
        .Where(query);