Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 选择具有所有标签的产品_C#_Linq_Entity Framework - Fatal编程技术网

C# 选择具有所有标签的产品

C# 选择具有所有标签的产品,c#,linq,entity-framework,C#,Linq,Entity Framework,我使用的是C#和实体框架。我有一个包含我的产品的Products表(Id,Name),一个包含所有可用标记的Tags表(Id,Name),以及一个用于为产品分配标记的ProductTags表(Id,ProductId,TagId)。 用户可以指定他想要查看具有多个标记的产品(Int[]selectedtagds)。 问题是:如何获取所有产品,其中每个产品都有用户指定的所有标签 现在我使用这个查询 `var reault = Context.Products

我使用的是C#和实体框架。我有一个包含我的产品的Products表(
Id,Name
),一个包含所有可用标记的Tags表(
Id,Name
),以及一个用于为产品分配标记的ProductTags表(
Id,ProductId,TagId
)。 用户可以指定他想要查看具有多个标记的产品(
Int[]selectedtagds
)。 问题是:如何获取所有产品,其中每个产品都有用户指定的所有标签

现在我使用这个查询

`var reault = Context.Products
                     .Where(x => SelectedTagIds.All(y => 
                           (x.ProductTags.Select(z => z.TagId))
                     .Contains(y)));`

我想知道这是一种正确的方法还是有更好/更快的方法?

您可以使用intersect,然后检查两者的长度,确保intersected的计数与搜索标记的计数相同,这意味着所有搜索标记都存在于ProductTags集合中

        var result =
            products.Where(
                x => x.ProductTags.Intersect(searchTags).Count() == searchTags.Length);
但是,您需要运行性能分析,这对您更有效。但正如Oren所评论的,您是否真的存在性能问题?因为这两个集合很可能都很小,所以不会造成瓶颈

编辑:刚刚检查了intersect的性能,它比使用.All with.Contains慢

在我的机器上执行,创建1000个结果查询,并使用ToList()对1000个产品(带有2个搜索标记)进行枚举,可获得以下性能:

searchTags.All(搜索=>x.ProductTags.Contains(搜索))
=202ms

!searchTags.Exception(x.ProductTags).Any()
=339ms

x.ProductTags.Intersect(searchTags).Count()==searchTags.Length
=389ms

如果您确实需要提高性能,您可以对ProductTags和SelectedTagDS使用HashSet

编辑2:使用哈希集比较

使用hashset运行比较,并获得以下输出:创建1000个查询对象,并使用ToList()执行到列表中,得到以下结果:

使用
列表

Creating Events took 6ms
Number of Tags = 3000
Number of Products = 1003
Average Number of Tags per Products = 100
Number of Search Tags = 10

.All.Contains = 5379ms - Found 51
.Intersect = 5823ms - Found 51
.Except = 6720ms - Found 51
Creating Events took 26ms
Number of Tags = 3000
Number of Products = 1003
Average Number of Tags per Products = 100
Number of Search Tags = 10

.All.Contains = 259ms - Found 51
.Intersect = 6417ms - Found 51
.Except = 7347ms - Found 51
使用
HashSet

Creating Events took 6ms
Number of Tags = 3000
Number of Products = 1003
Average Number of Tags per Products = 100
Number of Search Tags = 10

.All.Contains = 5379ms - Found 51
.Intersect = 5823ms - Found 51
.Except = 6720ms - Found 51
Creating Events took 26ms
Number of Tags = 3000
Number of Products = 1003
Average Number of Tags per Products = 100
Number of Search Tags = 10

.All.Contains = 259ms - Found 51
.Intersect = 6417ms - Found 51
.Except = 7347ms - Found 51

如您所见,使用HashSet的速度要快得多,即使您将额外的20ms用于创建HashSet也是如此。尽管散列是ID字段的简单散列。如果使用更复杂的散列,结果会有所不同。

您是有实际的性能问题还是试图提前优化?@Oren我正在尝试提前优化,因为项目正在开发中,db中只有10个测试产品/3个测试标记……优化的最佳方法是避免理论化和实际上,保留了大量的标签、产品及其关联——最好是比您预期的未来稍大一点。然后,您可以测试性能是否可以接受,而不是猜测不同的方法是否更好。