代码之家  ›  专栏  ›  技术社区  ›  Erick

Linq中的“IN”运算符

  •  13
  • Erick  · 技术社区  · 15 年前

    我正在尝试使用实体框架在Linq中转换一个旧的原始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,因为很明显该属性不在那里,因为它返回一个IQueryable。。。

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

    有什么提示吗?

    [编辑]

    这是完整的查询代码。。。我试着在第二个表达式上使用contains,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类不包含任何对产品的引用,我想我将不得不进行连接查询,这里没有任何线索。

    14 回复  |  直到 15 年前
        1
  •  17
  •   spadelives    12 年前
    var activeMembers = (
    from member in db.ContactSet
    where activeProducts.Select(x=>x.ID).Contains(member.ID));
    
        2
  •  5
  •   SLaks    15 年前

    where activeProducts.Contains(member.ID) .
    ToString s

        3
  •  4
  •   Craig Stuntz    15 年前

    var q = from member in db.ContactSet
            where member.Products.Any(p => p.IsActive)
            select member;
    
        4
  •  1
  •   spot    15 年前
        5
  •  1
  •   Ashley Jackson    13 年前

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

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

    灰烬。。

        6
  •  1
  •   Servy    12 年前
    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
    
        7
  •  0
  •   Eric Petroelje    15 年前

    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));
    
        8
  •  0
  •   Matthias    15 年前

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

    where activeProducts.Contains(member.ID)
    
        9
  •  0
  •   Manish Basantani    15 年前

    这个怎么样。。。

    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()));
    
        10
  •  0
  •   herzmeister    15 年前

    当查询内存中的对象时,助手或扩展方法可以很好地工作。但对于SQL数据库,您的LINQ代码将被编译成表达式树,进行分析并转换为SQL命令。此功能没有自定义扩展方法或其他对象的方法的概念,例如 .Contains(...)

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

    您所能做的就是创建自己的QueryProvider,它与SQL数据库相冲突。但这将是困难的,这将是唯一的一个 in 只有你缺少的功能。

    然而,如果你真的想走这条路,那就尽情享受吧: LINQ: BUILDING AN IQUERYABLE PROVIDER SERIES

        11
  •  0
  •   Erick    15 年前

        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();
    
        12
  •  0
  •   Rishikesh    12 年前
        13
  •  0
  •   Konrad Viltersten    12 年前
    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));
    
        14
  •  0
  •   Aron    12 年前

    如果不知道确切的映射,就很难判断什么可以做,什么不能做。我会假设没有任何演员参与。首先,您必须记住Linq表达式树中的所有内容在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表达式捕获非灵长类(DateTime、int、string等)和非ORM类(DataContext/EntityObject等)。另一个主要问题是使用ORM未公开的函数和运算符(可以通过ORM将用户定义的函数映射到.net函数,但由于索引问题,我不建议这样做)。