Linq的“IN”操作员

我试图在Linq中使用Entity Framework转换旧的原始Sql查询。

它使用IN运算符和一组项目。 查询是这样的:

SELECT Members.Name FROM Members WHERE Members.ID IN ( SELECT DISTINCT ManufacturerID FROM Products WHERE Active = 1) ORDER BY Members.Name ASC 

由于子查询的返回不是单个字符串而是字符串集合,因此我无法使用String.Contains()方法。

我想过做的事情:

 var activeProducts = ( from products in db.ProductSet where product.Active == true select product.ManufacturerID); 

然后

 var activeMembers = ( from member in db.ContactSet where member.ID.ToString().Contains(activeProducts)); 

但它停止在包含说它有无效的参数…我不能选择activeProducts.ManufacturerID,因为很明显,proprety不存在,因为它返回一个IQueryable …

我在这里要做的就是返回一个至少有一个活跃产品的成员列表。

任何提示?

[编辑]

这是完整的查询代码…我尝试使用第二个表达式的包含,Linq似乎不喜欢它:

Server Error in '/' Application. LINQ to Entities does not recognize the method 'Boolean Contains[String](System.Linq.IQueryable``1[System.String], System.String)' method, and this method cannot be translated into a store expression.

  var activeProduct =(from product in Master.DataContext.ProductSet where product.Active == true && product.ShowOnWebSite == true && product.AvailableDate = DateTime.Today ) select product.ManufacturerID.ToString() ); var activeArtists = from artist in Master.DataContext.ContactSet where activeProduct.Contains(artist.ID.ToString()) select artist; NumberOfArtists = activeArtists.Count(); artistsRepeater.DataSource = activeArtists; artistsRepeater.DataBind(); 

[更多细节] ManufacturerID显然是一个可以为空的GUID ……

由于某种原因,ContactSet类不包含对产品的任何引用,我想我将不得不进行连接查询,这里没有线索。

 var activeMembers = ( from member in db.ContactSet where activeProducts.Select(x=>x.ID).Contains(member.ID)); 

尝试where activeProducts.Contains(member.ID)
编辑 :你没有任何ToString s尝试过吗?

您可以在一个查询中执行此操作:

 var q = from member in db.ContactSet where member.Products.Any(p => p.IsActive) select member; 
 from m in members where products.Any(p => p.Active && p.ManufacturerID == m.ID) select m 

要么

 from m in members join p in products on m.ID equals p.ManufacturerID where p.Active select m 

尝试Colin Meek发布的解决方案: http : //social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/095745fe-dcf0-4142-b684-b7e4a1ab59f0/ 。 它对我有用。

那这个呢:

 from m in members where products.FirstOrDefault(prod => prod.IsActive == 1 && prod.Id == m.Id) != null select m; 

你可以使用&&链接where子句中所需的任意数量的条件

灰..

而不是这个:

 var activeMembers = ( from member in db.ContactSet where member.ID.ToString().Contains(activeProducts)); 

试试这个:

 var activeMembers = ( from member in db.ContactSet where activeProducts.Contains(member.ID)); 

如果您交换语句(未经测试)怎么办?

 where activeProducts.Contains(member.ID) 

这个怎么样…

 var activeProducts = ( from products in db.ProductSet where product.Active == true select product.ManufacturerID); var activeMembers = ( from member in db.ContactSet where activeProducts.Contains(member.ID.ToString())); 

查询内存中的对象时,帮助器或扩展方法可以正常工作。 但是对于SQL数据库,您的LINQ代码将被编译到表达式树中,进行分析并转换为SQL命令。 此function没有定制扩展方法或其他对象(如.Contains(...)方法的概念。

它可以很容易地通过Microsoft实现到标准的LINQ-To-SQLfunction中。 但只要他们不想要,我们就会无助,只要它不是开源function。

您所能做的就是创建一个与SQL数据库相对应的QueryProvider。 但是它很难,只有那个infunction上的你才会失踪。

但是,如果你真的想走那条路,那就玩得开心: LINQ:构建一个不可思议的提供商系列

最后我设法编写了一些非常难看的东西,但这确实有效! (大声笑)

  var activeProduct =(from product in Master.DataContext.ProductSet where product.Active == true && product.ShowOnWebSite == true && product.AvailableDate <= DateTime.Today && ( product.DiscontinuationDate == null || product.DiscontinuationDate >= DateTime.Today ) select product.ManufacturerID ).Distinct(); var artists = from artist in Master.DataContext.ContactSet select artist; List activeArtists = new List(); foreach (var artist in artists) { foreach(var product in activeProduct) { if (product.HasValue && product.Value == artist.ID) activeArtists.Add(artist); } } NumberOfArtists = activeArtists.Count(); artistsRepeater.DataSource = activeArtists; artistsRepeater.DataBind(); 

我已经在http://www.codeproject.com/Tips/336253/Filtering-records-from-List-based-similar-to-Sql-I上发布了相同的内容

 var q = (from p in db.DOCAuditTrails where p.ActionUser == "MyUserID" && p.ActionTaken == "Not Actioned" && p.ActionDate > DateTime.Parse("2011-09-13") select p.RequisitionId).Distinct(); var DocAuditResults = db.DOCAuditTrails.Where(p => q.ToArray().Contains(p.RequisitionId)); 

在不知道确切的映射的情况下,很难分辨出可以做什么和什么做不到。 我会假设没有涉及任何演员。 首先,您必须记住Linq表达式树中的所有内容都必须具有SQL中的等效项。 正如其他人所说,你的Linq语句中有一个object.ToString()。

然而,似乎人们忽略了提到的是你有两个用法对象.ToSting(),两者都必须被删除。

我还会创建一个额外的变量来将闭包的捕获类型更改为显式的DataContext(因为Linq语句就像一个lambda,并且延迟评估。它需要占用整个Master变量。之前我说过所有内容你的Linq必须在SQL中有一个等价物。鉴于Master不可能存在于SQL中,Master的类型没有DataContext属性/列/映射。

 var context = Master.DataContext; var activeProduct = from product in context.ProductSet where product.Active == true && product.ShowOnWebSite == true && product.AvailableDate <= DateTime.Today && ( product.DiscontinuationDate == null || product.DiscontinuationDate >= DateTime.Today ) select product.ManufacturerID; var activeArtists = from artist in context.ContactSet where activeProduct.Contains(artist.ID) select artist; 

我希望上述更改对您有用。

在许多情况下,Linq到ORM的问题可以追溯到您的Linq Expression捕获非主要(DateTime,int,string等)和非基于ORM的类(DataContext / EntityObject等)。 另一个主要问题是使用ORM未公开的函数和运算符(可以通过ORM将用户定义的函数映射到.net函数,但由于索引问题,我不建议使用它)。