如何解决如何将LINQ to SQL Distinct运算符应用于List <T>?
| 我在LINQ to sql中遇到严重的问题(这使我发疯了)。我正在Visual Studio 2010中使用c#和Razor开发ASP.NET MVC3应用程序。 我有两个数据库表,产品和类别: 产品(Prod_Id [主键],其他属性) 类别((Dept_Id,Prod_Id)[主键],其他属性) 显然,类别中的Prod_Id是外键。这两个类均使用实体框架(EF)进行映射。为了简单起见,我没有提及应用程序的上下文。 在类别中,有多行包含Prod_Id。我想对所有类别中的不同Prod_Id进行投影。我根据以下(非常简单的)查询在sql Server MGMT Studio中使用普通(T)sql进行了此操作:SELECT disTINCT Prod_Id
FROM Categories
结果是正确的。现在,我需要在应用程序中进行此查询,因此我使用了:
var query = _StoreDB.Categories.Select(m => m.Prod_Id).distinct();
我使用以下方法检查查询结果:
query.Select(m => m.Prod_Id);
要么
foreach(var item in query)
{
item.Prod_Id;
//other instructions
}
它不起作用。首先,当我尝试编写query.Select(m => m.
或item.
时,Intellisense仅显示有关方法的建议(例如Equals等),而不是属性。我以为Intellisense可能有问题(我想大多数人都希望Intellisense是错误的:-D),但是当我启动应用程序时,我在运行时收到错误消息。
在给出答案之前,请记住:
1)我检查了很多论坛,我尝试了普通的LINQ to sql(不使用lambdas),但是它不起作用。它在(T)sql中起作用的事实意味着LINQ to sql指令存在问题(我的应用程序中的其他查询可以正常工作)。
2)由于与应用程序相关的原因,我使用了一个List<T>
变量而不是_StoreDB.Categories,我认为这就是问题所在。如果您能为我提供不使用ѭ6的解决方案,也将不胜感激。
谢谢你的回答
弗朗切斯科解决方法
这行:
var query = _StoreDB.Categories.Select(m => m.Prod_Id).Distinct();
您的LINQ查询最有可能返回ints
的IEnumerable ...(以Select(m => m.Prod_Id)
判断)。您具有整数列表,而不是实体对象列表。尝试打印它们,然后看得到什么。,调用_StoreDB.Categories.Select(m => m.Prod_Id)
意味着query
将仅包含Prod_Id
值,而不包含整个实体。这将大致等效于此SQL,该SQL仅选择一列(而不是整个行):
SELECT Prod_Id FROM Categories;
因此,当您使用foreach (var item in query)
遍历query
时,item
的类型可能是int
(或任何您的Prod_Id
列),而不是您的实体。这就是为什么Intellisense不显示您键入\“item.
\”时期望的实体属性的原因...
如果要将want21ѭ中的所有列都包含在query
中,则甚至不需要使用.Select(m => m)
。您可以这样做:
var query = _StoreDB.Categories.Distinct();
请注意,如果您未将IEqualityComparer<T>
显式传递给Distinct()
,则将使用EqualityComparer<T>.Default
(取决于T
的类型,是否实现System.IEquatable<T>
,其行为可能与您想要的方式不同)。 。
有关使30英镑在与您相似的情况下工作的更多信息,请查看此问题或相关问题以及相关讨论。,正如其他答案所解释的那样,OP遇到的错误是因为他的代码的结果是一个整数集合,而不是一个类别集合。
尚未得到答案的是他的问题,即如何在联接中使用int集合或其他方法以获取一些有用的数据。我将在这里尝试这样做。
现在,我不太确定为什么OP希望从类别中获得不同的Prod_Id列表,而不仅仅是从Projects中获得Prod_Id。也许他想找出与一个或多个类别相关的产品,因此任何未归类的产品都将从结果中排除。我假设是这种情况,并且期望的结果是具有相关类别的不同产品的集合。我将首先回答有关如何处理Prod_Id的问题,然后提供一些替代方法。
我们可以完全按照问题中创建的Prod_Ids的集合进行查询:
var query = _StoreDB.Categories.Select(m => m.Prod_Id).Distinct();
然后,我们将使用join,如下所示:
var products = query.Join(_StoreDB.Products,id => id,p => p.Prod_Id,(id,p) => p);
这将获取查询,将其与Products表连接,指定要使用的键,最后说要从每个匹配集中返回Product实体。因为我们知道查询中的Prod_Id是唯一的(因为Distinct()),而产品中的Prod_Ids是唯一的(根据定义,因为它是主键),所以我们知道结果将是唯一的,而不必调用Distinct() 。
现在,以上方法将获得理想的结果,但是绝对不是最干净或最简单的方法。如果使用关联属性定义Category实体,该属性从Products返回相关记录(可能会称为Product),则执行我们要执行的操作的最简单方法如下:
var products = _StoreDB.Categories.Select(c => c.Product).Distinct();
这将从每个类别中获取产品,并返回它们的不同集合。
如果Category实体不具有Product关系属性,那么我们可以返回使用Join函数来获取我们的Products。
var products = _StoreDB.Categories.Join(_StoreDB.Products,c => c.Prod_Id,(c,p) => p).Distinct();
最后,如果我们不只是想要一个简单的产品集合,那么就必须进行更多的研究,也许最简单的事情是在遍历产品时进行处理。另一个示例是获取每个产品所属类别的数量的计数。如果是这种情况,我将颠倒逻辑并从Products开始,如下所示:
var productsWithCount = _StoreDB.Products.Select(p => new { Product = p,NumberOfCategories = _StoreDB.Categories.Count(c => c.Prod_Id == p.Prod_Id)});
这将导致一个匿名类型的对象的集合,这些对象引用该产品以及与该产品相关的NumberOfCategories。如果我们仍然需要排除任何未修饰的产品,则可以在分号前附加ѭ36。当然,如果使用相关类别的关系属性定义了Product实体,则不需要此属性,因为您可以选择任何Product并执行以下操作:
int NumberOfCategories = product.Categories.Count();
无论如何,对不起,您不满意。我希望这对遇到类似问题的其他人有帮助。 ;)版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。