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。 但是它很难,只有那个in
function上的你才会失踪。
但是,如果你真的想走那条路,那就玩得开心: 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函数,但由于索引问题,我不建议使用它)。