Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用实体框架查询多个(~100)搜索词_C#_Entity Framework_Entity Framework 5 - Fatal编程技术网

C# 使用实体框架查询多个(~100)搜索词

C# 使用实体框架查询多个(~100)搜索词,c#,entity-framework,entity-framework-5,C#,Entity Framework,Entity Framework 5,我需要在我的数据库上做一个类似这样的查询,实际上可能有100个或更多的搜索词 public IQueryable<Address> GetAddressesWithTown(string[] towns) { IQueryable<Address> addressQuery = DbContext.Addresses; addressQuery.Where( x => towns.Any( y=> x.Town == y ) ); re

我需要在我的数据库上做一个类似这样的查询,实际上可能有100个或更多的搜索词

public IQueryable<Address> GetAddressesWithTown(string[] towns)
{
    IQueryable<Address> addressQuery = DbContext.Addresses;
    addressQuery.Where( x => towns.Any( y=> x.Town == y ) );
    return addressQuery;
}
public IQueryable GetAddressesWithTown(字符串[]towns)
{
IQueryable addressQuery=DbContext.Addresses;
其中(x=>towns.Any(y=>x.Town==y));
返回地址查询;
}
但是,当它包含超过15个术语时,它会在执行时抛出异常,因为生成的SQL太长

这种查询可以通过
实体框架
完成吗


还有什么其他选项可以完成这样的查询?

这看起来像是一个场景,您需要使用,因为这将帮助您创建基于Or的谓词并构造动态lambda表达式

这是创建LinqPad的Joseph Albahari创建的名为LinqKit的库的一部分

 public IQueryable<Address> GetAddressesWithTown(string[] towns)
{
  var predicate = PredicateBuilder.False<Address>();

  foreach (string town in towns)
  {
    string temp = town;
    predicate = predicate.Or (p => p.Town.Equals(temp));
  }

  return DbContext.Addresses.Where (predicate);
}
public IQueryable GetAddressesWithTown(字符串[]towns)
{
var predicate=PredicateBuilder.False();
foreach(城镇中的城镇)
{
字符串温度=城镇;
谓词=谓词或(p=>p.Town.Equals(temp));
}
返回DbContext.Addresses.Where(谓词);
}

这看起来像是您希望使用的场景,因为这将帮助您创建基于Or的谓词并构造动态lambda表达式

这是创建LinqPad的Joseph Albahari创建的名为LinqKit的库的一部分

 public IQueryable<Address> GetAddressesWithTown(string[] towns)
{
  var predicate = PredicateBuilder.False<Address>();

  foreach (string town in towns)
  {
    string temp = town;
    predicate = predicate.Or (p => p.Town.Equals(temp));
  }

  return DbContext.Addresses.Where (predicate);
}
public IQueryable GetAddressesWithTown(字符串[]towns)
{
var predicate=PredicateBuilder.False();
foreach(城镇中的城镇)
{
字符串温度=城镇;
谓词=谓词或(p=>p.Town.Equals(temp));
}
返回DbContext.Addresses.Where(谓词);
}

您大致有两种选择:

  • 您可以将
    。任何
    替换为
    。包含
    替代项
  • 可以将普通SQL与表值参数一起使用
使用
.Contains
更容易实现,并有助于提高性能,因为它在
子句中转换为内联sql
;所以100个城镇应该不是问题。但是,这也意味着确切的sql取决于确切的城镇数量:您正在强制sql server为每个城镇数量重新编译查询。当查询复杂时,这些重新编译可能会很昂贵;它们还可以从缓存中逐出其他查询计划

使用表值参数是更通用的解决方案,但要实现它需要更多的工作,特别是因为这意味着您需要自己编写SQL查询,并且不能依赖实体框架。(使用
ObjectContext.Translate
您仍然可以将查询结果解包为强类型对象,尽管编写了sql)。不幸的是,您还不能使用实体框架将大量数据高效地传递给sql server。实体框架既不支持表值参数,也不支持临时表(不过,它是一个

一点TVPSQL看起来像这样
select。。。从…起在townArg.town=address.town上加入@townTableArg townArg。。。从…起where address.town in(从@townTableArg中选择town)

您可能可以绕过EF限制,但它不会很快,而且可能会很棘手。一种解决方法是将您的值插入到某个中间表中,然后使用该表进行连接——这仍然是100个插入,但这些是单独的语句。如果EF的未来版本支持,这实际上可能是合理的

几乎等同于表值参数的方法是批量插入到临时表中,并在查询中与临时表联接。大多数情况下,这只意味着您的表名将以“#”而不是“@”开头:-)。temp表的开销稍大一些,但您可以在其上放置索引,在某些情况下,这意味着后续查询将更快(对于真正庞大的数据量)

不幸的是,从C#使用临时表或批量插入都是一件麻烦事。这里最简单的解决方案是制作一个
数据表
;这可以传递给任何一方。然而,数据表相对较慢;一旦开始添加数百万行,over可能就与此相关。最快(通用)的解决方案是实现定制的
IDataReader
,几乎与
IEnumerable
一样快

顺便说一下,要使用表值参数,需要在服务器上声明表参数的形状(“类型”);如果使用临时表,也需要创建它

以下是一些让您开始学习的建议:


    • 您大致有两种选择:

      • 您可以将
        。任何
        替换为
        。包含
        替代项
      • 可以将普通SQL与表值参数一起使用
      使用
      .Contains
      更容易实现,并有助于提高性能,因为它在
子句中转换为内联sql
;所以100个城镇应该不是问题。但是,这也意味着确切的sql取决于确切的城镇数量:您正在强制sql server为每个城镇数量重新编译查询。当查询复杂时,这些重新编译可能会很昂贵;它们还可以从缓存中逐出其他查询计划

使用表值参数是更通用的解决方案,但要实现它需要更多的工作,特别是因为这意味着您需要自己编写SQL查询,并且不能依赖实体框架。(使用
ObjectContext.Translate
您仍然可以将查询结果解包为强类型对象,尽管编写了sql)。不幸的是,您还不能使用实体框架将大量数据高效地传递给sql server。实体框架既不支持表值参数,也不支持临时表(不过,它是一个

一点TVPSQL看起来像这样
select。。。从…起在townArg.town=address.town上加入@townTableArg townArg