简体   繁体   English

LINQ 检查列表是否包含另一个列表中的任何项目 mysql 语法错误

[英]LINQ check if a list contains any item from another list mysql syntax error

I'm using LINQ with MySql我在 MySql 中使用 LINQ

Mysql version: 5.7.21-log Mysql 版本: 5.7.21-log

EntityFramework : v6.0.0.0 v6.0.0.0v6.0.0.0

Mysql.Data : v6.9.12.0 Mysql.Data : v6.9.12.0

MySql.Data.Entity.EF6: v6.9.12.0 (I'm not using MySql.Data.Entity ) MySql.Data.Entity.EF6: v6.9.12.0 (我没有使用MySql.Data.Entity

Query询问

var keywords = new List<string>();
keywords.Add("keyword1");
var query = dbContext.ads.Where(x => keywords.Any(y => x.Title.Contains(y)));

Explanation ads is a table in database, sample data:说明ads是数据库中的一个表,示例数据: 在此处输入图片说明

Get records where Title contains any of the keyword获取Title包含任何keyword

Exception例外

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%keyword1%))) AS `GroupBy1`' at line 10

Complete Exception:完全异常:

System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> MySql.Data.MySqlClient.MySqlException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%keyword1%)' at line 10
   at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
   at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
   at MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int64& insertedId)
   at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
   at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
   at MySql.Data.EntityFramework.EFMySqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext`1 c)
   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
   at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
   --- End of inner exception stack trace ---
   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
   at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__6()
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5()
   at System.Data.Entity.Infrastructure.DefaultExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0()
   at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at ExamBuilder.Controllers.ExamController.EnterExam()

Internal SQL query内部 SQL 查询

SELECT
`Extent1`.`packageMasterId`, 
`Extent1`.`title`, 
`Extent1`.`packageStatus`, 
`Extent1`.`packageCreationDate`, 
`Extent1`.`basePrice`, 
`Extent1`.`validity`
FROM `package_master` AS `Extent1`
 WHERE EXISTS(SELECT
1 AS `C1`
FROM (SELECT
1 AS `X`) AS `SingleRowTable1`
 WHERE `Extent1`.`tile` LIKE %keyword1%)

How can I modify the query to get those recrods whose title contains any of the keyword ?如何修改查询以获取title包含任何keyword

Update:更新:

Question is not duplicate The linked question uses same query that I have used but i'm getting exception with mysql!问题不重复链接的问题使用与我使用过的相同的查询,但我遇到了 mysql 异常!

I've managed to reproduce your error with the versions of Entity Framework and MySql.Data.* libraries.我已经设法用Entity FrameworkMySql.Data.*库的版本重现了您的错误。 Bumping the version to the highest 6.*.* available could not help, so here is my workaround using the SqlQuery .将版本提高到可用的最高6.*.*无济于事,所以这是我使用SqlQuery解决方法。

 var keywords = new List<string>() { "Test123", "TestASD" };

 var likeStatements = keywords.Select(keyword => $"title LIKE '%{keyword}%'");
 var whereClauseBody = string.Join(" OR ", likeStatements.ToArray());

 var query = context.Ads
                    .SqlQuery($"select * from stack_linq.ads where {whereClauseBody};");

Notes:笔记:

  • stack_linq is the schema name. stack_linq是架构名称。 Change it to your schema name.将其更改为您的架构名称。 If you have the schema name specified by default in your <connectionStrings> then the SqlQuery can be changed to $"select ads where ...如果您在<connectionStrings>默认指定了架构名称,则可以将SqlQuery更改为$"select ads where ...
  • in title LIKE ... change the name of the column (eg if it should be Title instead of title )title LIKE ...更改列的名称(例如,如果它应该是Title而不是title
  • My App.config file:我的App.config文件:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <connectionStrings>
    <add name="StackMySqlContext" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;port=3306;database=stack_linq;uid=root;password=mysql" />
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="mssqllocaldb" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.12.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"></provider>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <remove invariant="MySql.Data.MySqlClient" />
      <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.12.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
    </DbProviderFactories>
  </system.data>
</configuration>

Links I've found useful to setup the MWE :我发现对设置MWE有用的链接:

Used Visual Studio version: Community 2017 (15.9.5)使用的 Visual Studio 版本:Community 2017 (15.9.5)

如果我正确理解您正在寻找的内容,则以下内容应该有效...

query = db.ads.Where(x => keywords.Contains(x.title));

I ran into the same bug with MySql.Data.Entity v6.10.9 .我遇到了与MySql.Data.Entity v6.10.9相同的错误。 Oddly, it only happened when the array had only 1 value.奇怪的是,它只发生在数组只有 1 个值时。 If my array had two or more values, it generated the correct SQL.如果我的数组有两个或多个值,它会生成正确的 SQL。 Therefore, my method ended up looking something like:因此,我的方法最终看起来像:

var query = null;
if (1 == keywords.Length) {
  // MySql.Data.Entity bug creates invalid SQL with only one value
  var keyword = keywords[0];
  query = dbContext.ads.Where(x => x.Title.Contains(keyword)));
} 
else {
  query = dbContext.ads.Where(x => keywords.Any(y => x.Title.Contains(y)));
}

try this:尝试这个:

query = db.ads.Where(x => x.Title.Contains(x.Keywords));

or:或者:

var title= db.ads.Select(x=>x.title).ToList();
query = db.ads.Where(x => title.Contains(x.keyword));

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

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