简体   繁体   English

如何将LINQ查询写入SQL IN

[英]How to write LINQ query to sql IN

I want to query my cosmosDB to get List of Documents of type ZonesDO && whose id are in UserPreferance.Zones My UserPreferance class is : 我想查询我的cosmosDB以获取ZonesDO &&类型的文档列表,其ID在UserPreferance.Zones中。我的UserPreferance类是:

public class UserPreference 
    {
        [JsonProperty("zones")]
        public List<Zone> Zones { get; set; }
    }

and Zone Class is: 区域类别为:

public class Zone
    {
        [JsonProperty("id")]
        public override Guid Id { get; set; }

        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("category")]
        public string Category { get; set; }
    }

I am trying this query but not able to complete it. 我正在尝试此查询,但无法完成它。

var zones = DbUtil.Client.CreateDocumentQuery<ZoneDO>(CollectionUri)
     .Where(z => z.Type == typeof(ZoneDO).ToString() && 
     *z.Id in user.UserPreference.Zones.ids*)// here I need the solution
     .AsEnumerable().ToList();

You can try to use Contain method. 您可以尝试使用Contain方法。

 var zones = DbUtil.Client.CreateDocumentQuery<ZoneDO>(CollectionUri)
     .Where(z => z.Type == typeof(ZoneDO).ToString() && 
      user.UserPreference.Zones.Select(x => x.Id).Contain(z.Id)).ToList();

Or you can use inline Where and Count 或者您可以使用内联WhereCount

var zones = DbUtil.Client.CreateDocumentQuery<ZoneDO>(CollectionUri)
     .Where(
        z => z.Type == typeof(ZoneDO).ToString() && 
        user.UserPreference.Zones.Where(a=> a.Id == z.Id).Count() > 0
      ).ToList();

Perform select on Zones.Id and then check with Contains to get desired result Zones.Id上执行选择,然后检查Contains以获取所需结果

var zones = DbUtil.Client.CreateDocumentQuery<ZoneDO>(CollectionUri)
     .Where(z => z.Type == typeof(ZoneDO).ToString() && 
    user.UserPreference.Zones.Select(x => x.Id).Contains(z.Id))
     .AsEnumerable().ToList();

Another option may be to use the Any() operator: 另一种选择是使用Any()运算符:

var zones = DbUtil.Client.CreateDocumentQuery<ZoneDO>(CollectionUri)
            .Where(z => z.Type == typeof(ZoneDO).ToString() && 
            user.UserPreference.Zones.Where(x => x.Id == z.Id).Any())
            .AsEnumerable().ToList();

Linq providers usually understands basic methods on arrays/collections. Linq提供程序通常了解数组/集合的基本方法。 Therefore you can use Contains method. 因此,您可以使用Contains方法。

var zones = DbUtil.Client.CreateDocumentQuery<ZoneDO>(CollectionUri)
     .Where(z => z.Type == typeof(ZoneDO).ToString() && 
     user.UserPreference.Zones.Contains(z.Id))
     .AsEnumerable().ToList();

So apparently you have a user . 因此,显然您有一个user This user has a UserPreference and this UserPreference has zero or more Zones . user具有一个UserPreference并且此UserPreference具有零个或多个Zones It seems that this user , and the Zones of this user's UserPreference is in local memory (not in a database. The Zones are IEnumerable and not IQueryable) 看来此user及其用户UserPreferenceZones位于本地内存中(而不是数据库中。这些Zones是IEnumerable而不是IQueryable)

Although you didn't specify, it seems that DbUtil.Client.CreateDocumentQuery<ZoneDO>(CollectionUri) returns an IQueryable<ZoneDO> 尽管您未指定,但似乎DbUtil.Client.CreateDocumentQuery<ZoneDO>(CollectionUri)返回IQueryable<ZoneDO>

You want all ZoneDo that have an Id that is an Id of one of the Zones in the one and only UserPreference of your user. 你希望所有的ZoneDo有一个ID,它是在一个的ID Zones的唯一UserPreference您的用户。

In baby steps: 在婴儿步骤中:

IEnumerable<Guid> zoneIds = user.Userpreference.Zones.Select(zone => zone.Id);
IQueryable<ZoneDO> allZoneDOs = DbUtil.Client.CreateDocumentQuery<ZoneDO>(CollectionUri);

IEnumerable<ZoneDO> requestedZoneDOs = allZoneDOs
    .Where(zoneDo => zoneIds.Contains(zoneDo.Id);

Until now no query is performed, nor any enumeration. 到现在为止,不执行任何查询,也不进行任何枚举。 To perform the query and return the fetched data as a List<ZoneDO> use .ToList() ; 要执行查询并以List<ZoneDO>返回获取的数据,请使用.ToList() ;

List<ZoneDO> documents = requestedZoneDOs.ToList();

TODO: if desired put all statements into one big LINQ statement. TODO:如果需要,将所有语句放入一个大LINQ语句中。 I doubt whether this will improve performance. 我怀疑这是否会提高性能。 It surely will deteriorate readability and thus maintainability. 它肯定会降低可读性,从而降低可维护性。

Did you notice that I did not do your type checking part. 您是否注意到我没有进行类型检查。 This was not needed, because function CreateDocumentQuery<ZoneDO> already returns a sequence f ZoneDo . 这不是必需的,因为函数CreateDocumentQuery<ZoneDO>已经返回一个序列f ZoneDo

If not, and there are other types in the returned sequence, use OfType<ZoneDo> instead of checking on string representation of the returned objects: 如果不是,并且返回序列中还有其他类型,请使用OfType<ZoneDo>而不是检查返回对象的字符串表示形式:

IQueryable<ZoneDO> allZoneDOs = DbUtil.Client
    .CreateDocumentQuery<ZoneDO>(CollectionUri)
    .OfType<ZoneDo>();

AsEnumerable is not needed. 不需要AsEnumerable IQueryable.ToList() will perform the query and convert the data to a list. IQueryable.ToList()将执行查询并将数据转换为列表。

AsEnumerable is only needed if you need the data in local memory to continue with LINQ statements that cannot be performed as IQueryable, like LINQ statements where you call local functions, or LINQ statements that cannot be translated into SQL. 仅当您需要本地内存中的数据才能继续无法以IQueryable身份执行的LINQ语句(例如调用本地函数的LINQ语句或无法转换为SQL的LINQ语句)时,才需要AsEnumerable

AsEnumerable will fetch the requested data per 'page'. AsEnumerable将在每个“页面”中获取请求的数据。 So if you only need the first (few) elements, you don't fetch the complete table, but only the first (few) pages. 因此,如果仅需要前几个元素,则无需获取完整的表,而仅获取前几个页面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM