2010-01-14 106 views
11

我想在这里用实体框架在Linq中转换旧的原始SQL查询。Linq中的“IN”运算符

它将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 
          && (product.DiscontinuationDate == null || product.DiscontinuationDate >= 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类不包含ny参考产品,我想我将不得不做一个连接查询,这里没有线索。

回答

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

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

+0

没有工作,得到了Linq错误。 – Erick

+0

是的,Linq仍然不喜欢它,我刚才发现ManufacturerID是一个Guid? (可为空)......如果我做了'选择ManufacturerID。值'我有这样的:LINQ to Entities不识别方法'布尔包含[Guid](System.Linq.IQueryable'1 [System.Guid],System.Guid)'方法,并且此方法不能被转换成存储表达。 – Erick

+0

这是否与IN运算符一样高效? – tofutim

0

取而代之的是:

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)); 
+0

试过了,Linq实际上并不喜欢它。 – Erick

+0

当你尝试时究竟发生了什么? – SLaks

+0

错误是在那里编辑=) – Erick

0

如果你交换的声明(未经测试)?

where activeProducts.Contains(member.ID) 
0

这个怎么样...

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())); 
+0

真的无法正常工作。 – Erick

+0

我认为这种变化将使工作... VAR activeProducts =( 从产品db.ProductSet 其中product.Active ==真 选择product.ManufacturerID); var activeMembers =( from db.ContactSet中的成员 其中activeProducts.Select(x => x.id).Contains(member.ID.ToString())); – spadelives

+0

'product.Active == true'有点多余,不是吗?只要'product.Active'就够了。 – Askolein

2

您可以在一个查询做到这一点:

var q = from member in db.ContactSet 
     where member.Products.Any(p => p.IsActive) 
     select member; 
+0

我不得不简化陈述,但对“where”有更多的条件......我编辑我的帖子以实际包含完整的代码。 – Erick

+1

您仍然可以在一个查询中执行此操作。将整个'where'子句移到'Any'调用。 – SLaks

+0

没有从ContactSet到ProductSet的链接apprently(哦,我怎么爱第三方软件修改),我想我将不得不做一个连接查询... – Erick

0

一个帮手或扩展方法在内存中物体打击查询时将正常工作。但是对于SQL数据库,您的LINQ代码将被编译到表达式树中,并被分析并转换为SQL命令。此功能没有定制扩展方法或其他对象的方法的概念,如.Contains(...)

虽然它可以很容易地由微软实现到标准的LINQ到SQL的功能。但只要他们不想要,只要它不是开源功能,我们就无能为力了。

你所能做的就是创建你自己的QueryProvider,它违背了SQL数据库。但是,这将是艰难的,只有那一个in功能,你失踪了。

但是,如果你真的想要走这条路,有乐趣:LINQ: BUILDING AN IQUERYABLE PROVIDER SERIES

0

最后,我设法代码的东西实在难看,但实际工作! (lol)

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<Evolution.API.Contact> activeArtists = new List<Evolution.API.Contact>(); 

    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(); 
0
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)); 
1

这个怎么样:

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

你可以使用链& &

灰我已经张贴了关于在任意数量的where子句中规定的条件..

2
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 
0

不知道确切的映射,这是很难说有什么可以做,什么不能。我会假定没有涉及任何投射。首先,您必须记住,Linq Expression树中的所有内容在SQL中必须具有相同的功能。正如其他人已经注意到的,你的Linq语句中有一个object.ToString()。

但是,似乎人们忽视提及的是,您有两种使用object.ToSting(),两者都必须删除。我会做一个额外的变量来将闭包的捕获类型改为显式的DataContext(因为Linq语句就像一个lambda,并且被延迟求值),它需要把整个主变量变成。声明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,字符串等)和非基于ORM的类(DataContext/EntityObject等)。另一个主要问题是ORM没有公开的函数和运算符的使用(可以通过ORM将用户定义的函数映射到.net函数,但由于索引问题,我不会推荐它)。