diff --git a/src/EFCore.Jet.Data/JetCommand.cs b/src/EFCore.Jet.Data/JetCommand.cs index 0940652..aef9065 100644 --- a/src/EFCore.Jet.Data/JetCommand.cs +++ b/src/EFCore.Jet.Data/JetCommand.cs @@ -288,7 +288,18 @@ namespace EntityFrameworkCore.Jet.Data InlineTopParameters(); FixParameters(); - return _connection.RowCount = InnerCommand.ExecuteNonQuery(); + _connection.RowCount = InnerCommand.ExecuteNonQuery(); + + //For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. + //For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1. + //This from from the docs, however, it actually seems to be returning 0 for things like CREATE TABLE/INDEX, EXEC + //Workaround this + var commandtype = newCommandText.Trim().Substring(0, 10); + if (commandtype.Contains("INSERT") || commandtype.Contains("UPDATE") || commandtype.Contains("DELETE")) + { + return _connection.RowCount; + } + return -1; } /// diff --git a/test/EFCore.Jet.FunctionalTests/Query/ComplexTypeQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/ComplexTypeQueryJetTest.cs index 5d4293d..aee654e 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/ComplexTypeQueryJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/ComplexTypeQueryJetTest.cs @@ -249,6 +249,13 @@ WHERE `c`.`ShippingAddress_AddressLine1` = @__entity_equality_address_0_AddressL """); } + public override async Task Complex_type_equals_null(bool async) + { + await base.Complex_type_equals_null(async); + + AssertSql(); + } + public override async Task Subquery_over_complex_type(bool async) { await base.Subquery_over_complex_type(async); diff --git a/test/EFCore.Jet.FunctionalTests/Query/FromSqlSprocQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/FromSqlSprocQueryJetTest.cs index 497b3ac..386a594 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/FromSqlSprocQueryJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/FromSqlSprocQueryJetTest.cs @@ -19,7 +19,7 @@ namespace EntityFrameworkCore.Jet.FunctionalTests.Query { await base.From_sql_queryable_stored_procedure(async); - AssertSql($@"`Ten Most Expensive Products`"); + AssertSql($@"EXEC `Ten Most Expensive Products`"); } public override async Task From_sql_queryable_stored_procedure_with_tag(bool async) @@ -29,14 +29,33 @@ namespace EntityFrameworkCore.Jet.FunctionalTests.Query AssertSql( $@"-- Stored Procedure -`Ten Most Expensive Products`"); +EXEC `Ten Most Expensive Products`"); } - public override async Task From_sql_queryable_stored_procedure_projection(bool async) + public override async Task From_sql_queryable_stored_procedure_with_caller_info_tag(bool async) { - await base.From_sql_queryable_stored_procedure_projection(async); + await base.From_sql_queryable_stored_procedure_with_caller_info_tag(async); - AssertSql(); + AssertSql( + """ +-- File: SampleFileName:13 + +[dbo].[Ten Most Expensive Products] +"""); + } + + public override async Task From_sql_queryable_stored_procedure_with_caller_info_tag_and_other_tags(bool async) + { + await base.From_sql_queryable_stored_procedure_with_caller_info_tag_and_other_tags(async); + + AssertSql( + """ +-- Before +-- File: SampleFileName:13 +-- After + +[dbo].[Ten Most Expensive Products] +"""); } public override async Task From_sql_queryable_stored_procedure_with_parameter(bool async) @@ -44,23 +63,23 @@ namespace EntityFrameworkCore.Jet.FunctionalTests.Query await base.From_sql_queryable_stored_procedure_with_parameter(async); AssertSql( - $@"p0='ALFKI' (Size = 4000) + $@"p0='ALFKI' (Size = 255) -`CustOrderHist` {AssertSqlHelper.Parameter("@CustomerID")} = {AssertSqlHelper.Parameter("@p0")}"); +EXEC `CustOrderHist` CustomerID = {AssertSqlHelper.Parameter("@p0")}"); } public override async Task From_sql_queryable_stored_procedure_re_projection_on_client(bool async) { await base.From_sql_queryable_stored_procedure_re_projection_on_client(async); - AssertSql($@"`Ten Most Expensive Products`"); + AssertSql($@"EXEC `Ten Most Expensive Products`"); } public override async Task From_sql_queryable_stored_procedure_composed_on_client(bool async) { await base.From_sql_queryable_stored_procedure_composed_on_client(async); - AssertSql($@"`Ten Most Expensive Products`"); + AssertSql($@"EXEC `Ten Most Expensive Products`"); } public override async Task From_sql_queryable_stored_procedure_with_parameter_composed_on_client(bool async) @@ -68,30 +87,30 @@ namespace EntityFrameworkCore.Jet.FunctionalTests.Query await base.From_sql_queryable_stored_procedure_with_parameter_composed_on_client(async); AssertSql( - $@"p0='ALFKI' (Size = 4000) + $@"p0='ALFKI' (Size = 255) -`CustOrderHist` {AssertSqlHelper.Parameter("@CustomerID")} = {AssertSqlHelper.Parameter("@p0")}"); +EXEC `CustOrderHist` CustomerID = {AssertSqlHelper.Parameter("@p0")}"); } public override async Task From_sql_queryable_stored_procedure_take_on_client(bool async) { await base.From_sql_queryable_stored_procedure_take_on_client(async); - AssertSql($@"`Ten Most Expensive Products`"); + AssertSql($@"EXEC `Ten Most Expensive Products`"); } public override async Task From_sql_queryable_stored_procedure_min_on_client(bool async) { await base.From_sql_queryable_stored_procedure_min_on_client(async); - AssertSql($@"`Ten Most Expensive Products`"); + AssertSql($@"EXEC `Ten Most Expensive Products`"); } private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); - protected override string TenMostExpensiveProductsSproc => "`Ten Most Expensive Products`"; + protected override string TenMostExpensiveProductsSproc => "EXEC `Ten Most Expensive Products`"; - protected override string CustomerOrderHistorySproc => "`CustOrderHist` @CustomerID = {0}"; + protected override string CustomerOrderHistorySproc => "EXEC `CustOrderHist` CustomerID = {0}"; } } diff --git a/test/EFCore.Jet.FunctionalTests/Query/NorthwindAggregateOperatorsQueryJetTest.ResultOperators.cs b/test/EFCore.Jet.FunctionalTests/Query/NorthwindAggregateOperatorsQueryJetTest.ResultOperators.cs index c9cbdca..c8a4a4a 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/NorthwindAggregateOperatorsQueryJetTest.ResultOperators.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/NorthwindAggregateOperatorsQueryJetTest.ResultOperators.cs @@ -1,5 +1,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Threading.Tasks; using EntityFrameworkCore.Jet.Data; using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities; @@ -1554,6 +1555,212 @@ FROM `Customers` AS `c` WHERE `c`.`CustomerID` IN ('ABCDE', 'ANATR')"); } + public override async Task Contains_with_local_enumerable_closure(bool async) + { + await base.Contains_with_local_enumerable_closure(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +""", + // + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` = 'ABCDE' +"""); + } + + public override async Task Contains_with_local_object_enumerable_closure(bool async) + { + await base.Contains_with_local_object_enumerable_closure(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +"""); + } + + public override async Task Contains_with_local_enumerable_closure_all_null(bool async) + { + await base.Contains_with_local_enumerable_closure_all_null(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE 0 = 1 +"""); + } + + public override async Task Contains_with_local_enumerable_inline(bool async) + { + // Issue #31776 + await Assert.ThrowsAsync( + async () => + await base.Contains_with_local_enumerable_inline(async)); + + AssertSql(); + } + + public override async Task Contains_with_local_enumerable_inline_closure_mix(bool async) + { + // Issue #31776 + await Assert.ThrowsAsync( + async () => + await base.Contains_with_local_enumerable_inline_closure_mix(async)); + + AssertSql(); + } + + public override async Task Contains_with_local_ordered_enumerable_closure(bool async) + { + await base.Contains_with_local_ordered_enumerable_closure(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +""", + // + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` = 'ABCDE' +"""); + } + + public override async Task Contains_with_local_object_ordered_enumerable_closure(bool async) + { + await base.Contains_with_local_object_ordered_enumerable_closure(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +"""); + } + + public override async Task Contains_with_local_ordered_enumerable_closure_all_null(bool async) + { + await base.Contains_with_local_ordered_enumerable_closure_all_null(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE 0 = 1 +"""); + } + + public override async Task Contains_with_local_ordered_enumerable_inline(bool async) + { + await base.Contains_with_local_ordered_enumerable_inline(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +"""); + } + + public override async Task Contains_with_local_ordered_enumerable_inline_closure_mix(bool async) + { + await base.Contains_with_local_ordered_enumerable_inline_closure_mix(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +""", + // + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ANATR') +"""); + } + + public override async Task Contains_with_local_read_only_collection_closure(bool async) + { + await base.Contains_with_local_read_only_collection_closure(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +""", + // + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` = 'ABCDE' +"""); + } + + public override async Task Contains_with_local_object_read_only_collection_closure(bool async) + { + await base.Contains_with_local_object_read_only_collection_closure(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +"""); + } + + public override async Task Contains_with_local_ordered_read_only_collection_all_null(bool async) + { + await base.Contains_with_local_ordered_read_only_collection_all_null(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE 0 = 1 +"""); + } + + public override async Task Contains_with_local_read_only_collection_inline(bool async) + { + await base.Contains_with_local_read_only_collection_inline(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +"""); + } + + public override async Task Contains_with_local_read_only_collection_inline_closure_mix(bool async) + { + await base.Contains_with_local_read_only_collection_inline_closure_mix(async); + + AssertSql( + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ALFKI') +""", + // + """ +SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE `c`.`CustomerID` IN ('ABCDE', 'ANATR') +"""); + } + public override async Task Contains_with_local_non_primitive_list_closure_mix(bool isAsync) { await base.Contains_with_local_non_primitive_list_closure_mix(isAsync); diff --git a/test/EFCore.Jet.FunctionalTests/Query/OwnedEntityQuerySqlServerTest.cs b/test/EFCore.Jet.FunctionalTests/Query/OwnedEntityQuerySqlServerTest.cs index 7fb8995..53e103f 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/OwnedEntityQuerySqlServerTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/OwnedEntityQuerySqlServerTest.cs @@ -57,7 +57,7 @@ LEFT JOIN `ModdleA24777` AS `m0` ON `r`.`Id` = `m0`.`RootId` WHERE `r`.`Id` = 3 ORDER BY `r`.`Id`, `m`.`Id`, `m0`.`Id` """, - // +// """ SELECT `l`.`ModdleAId`, `l`.`UnitThreshold`, `t`.`Id`, `t`.`Id0`, `t`.`Id1` FROM ( @@ -167,7 +167,31 @@ ORDER BY `r`.`Buyer` """ SELECT `r`.`Id`, `r`.`Rot_ApartmentNo`, `r`.`Rot_ServiceType` FROM `RotRutCases` AS `r` -WHERE `r`.`Rot_ApartmentNo` IS NOT NULL AND `r`.`Rot_ServiceType` IS NOT NULL +WHERE `r`.`Rot_ApartmentNo` IS NOT NULL OR `r`.`Rot_ServiceType` IS NOT NULL +"""); + } + + public override async Task Owned_entity_with_all_null_properties_in_compared_to_null_in_conditional_projection(bool async) + { + await base.Owned_entity_with_all_null_properties_in_compared_to_null_in_conditional_projection(async); + + AssertSql( + """ +SELECT IIF(`r`.`Rot_ApartmentNo` IS NULL AND `r`.`Rot_ServiceType` IS NULL, TRUE, FALSE), `r`.`Rot_ApartmentNo`, `r`.`Rot_ServiceType` +FROM `RotRutCases` AS `r` +ORDER BY `r`.`Id` +"""); + } + + public override async Task Owned_entity_with_all_null_properties_in_compared_to_non_null_in_conditional_projection(bool async) + { + await base.Owned_entity_with_all_null_properties_in_compared_to_non_null_in_conditional_projection(async); + + AssertSql( + """ +SELECT IIF(`r`.`Rot_ApartmentNo` IS NOT NULL OR `r`.`Rot_ServiceType` IS NOT NULL, TRUE, FALSE), `r`.`Rot_ApartmentNo`, `r`.`Rot_ServiceType` +FROM `RotRutCases` AS `r` +ORDER BY `r`.`Id` """); } diff --git a/test/EFCore.Jet.FunctionalTests/Query/SqlExecutorJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/SqlExecutorJetTest.cs index 119a8a2..815b005 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/SqlExecutorJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/SqlExecutorJetTest.cs @@ -9,6 +9,8 @@ using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit.Abstractions; +using Microsoft.EntityFrameworkCore; +using Xunit; namespace EntityFrameworkCore.Jet.FunctionalTests.Query { @@ -26,7 +28,7 @@ namespace EntityFrameworkCore.Jet.FunctionalTests.Query { await base.Executes_stored_procedure(async); - AssertSql($@"`Ten Most Expensive Products`"); + AssertSql($@"EXEC `Ten Most Expensive Products`"); } public override async Task Executes_stored_procedure_with_parameter(bool async) @@ -36,7 +38,7 @@ namespace EntityFrameworkCore.Jet.FunctionalTests.Query AssertSql( $@"{AssertSqlHelper.Declaration("@CustomerID='ALFKI' (Nullable = false) (Size = 5)")} -`CustOrderHist` @CustomerID"); +EXEC `CustOrderHist` CustomerID"); } public override async Task Executes_stored_procedure_with_generated_parameter(bool async) @@ -44,77 +46,163 @@ namespace EntityFrameworkCore.Jet.FunctionalTests.Query await base.Executes_stored_procedure_with_generated_parameter(async); AssertSql( - $@"{AssertSqlHelper.Declaration("@p0='ALFKI' (Size = 4000)")} + $@"{AssertSqlHelper.Declaration("@p0='ALFKI' (Size = 255)")} -`CustOrderHist` @CustomerID = {AssertSqlHelper.Parameter("@p0")}"); +EXEC `CustOrderHist` CustomerID = {AssertSqlHelper.Parameter("@p0")}"); } public override async Task Query_with_parameters(bool async) { - await base.Query_with_parameters(async); + var city = "London"; + var contactTitle = "Sales Representative"; + + using var context = CreateContext(); + + var actual = async + ? await context.Database.ExecuteSqlRawAsync( + @"SELECT COUNT(*) FROM `Customers` WHERE `City` = {0} AND `ContactTitle` = {1}", city, contactTitle) + : context.Database.ExecuteSqlRaw( + @"SELECT COUNT(*) FROM `Customers` WHERE `City` = {0} AND `ContactTitle` = {1}", city, contactTitle); + + Assert.Equal(-1, actual); AssertSql( $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 255)")} {AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 255)")} -SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@p0")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@p1")}"); +SELECT COUNT(*) FROM `Customers` WHERE `City` = {AssertSqlHelper.Parameter("@p0")} AND `ContactTitle` = {AssertSqlHelper.Parameter("@p1")}"); } public override async Task Query_with_dbParameter_with_name(bool async) { - await base.Query_with_dbParameter_with_name(async); + var city = CreateDbParameter("@city", "London"); + + using var context = CreateContext(); + + var actual = async + ? await context.Database.ExecuteSqlRawAsync(@"SELECT COUNT(*) FROM `Customers` WHERE `City` = @city", city) + : context.Database.ExecuteSqlRaw(@"SELECT COUNT(*) FROM `Customers` WHERE `City` = @city", city); + + Assert.Equal(-1, actual); AssertSql( $@"{AssertSqlHelper.Declaration("@city='London' (Nullable = false) (Size = 6)")} -SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@city")}"); +SELECT COUNT(*) FROM `Customers` WHERE `City` = {AssertSqlHelper.Parameter("@city")}"); } public override async Task Query_with_positional_dbParameter_with_name(bool async) { - await base.Query_with_positional_dbParameter_with_name(async); + var city = CreateDbParameter("@city", "London"); + + using var context = CreateContext(); + + var actual = async + ? await context.Database.ExecuteSqlRawAsync(@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {0}", city) + : context.Database.ExecuteSqlRaw(@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {0}", city); + + Assert.Equal(-1, actual); AssertSql( $@"{AssertSqlHelper.Declaration("@city='London' (Nullable = false) (Size = 6)")} -SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@city")}"); +SELECT COUNT(*) FROM `Customers` WHERE `City` = {AssertSqlHelper.Parameter("@city")}"); } public override async Task Query_with_positional_dbParameter_without_name(bool async) { - await base.Query_with_positional_dbParameter_without_name(async); + var city = CreateDbParameter(name: null, value: "London"); + + using var context = CreateContext(); + + var actual = async + ? await context.Database.ExecuteSqlRawAsync(@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {0}", city) + : context.Database.ExecuteSqlRaw(@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {0}", city); + + Assert.Equal(-1, actual); AssertSql( $@"{AssertSqlHelper.Declaration("@p0='London' (Nullable = false) (Size = 6)")} -SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@p0")}"); +SELECT COUNT(*) FROM `Customers` WHERE `City` = {AssertSqlHelper.Parameter("@p0")}"); } public override async Task Query_with_dbParameters_mixed(bool async) { - await base.Query_with_dbParameters_mixed(async); + var city = "London"; + var contactTitle = "Sales Representative"; + + var cityParameter = CreateDbParameter("@city", city); + var contactTitleParameter = CreateDbParameter("@contactTitle", contactTitle); + + using var context = CreateContext(); + + var actual = async + ? await context.Database.ExecuteSqlRawAsync( + @"SELECT COUNT(*) FROM `Customers` WHERE `City` = {0} AND `ContactTitle` = @contactTitle", city, + contactTitleParameter) + : context.Database.ExecuteSqlRaw( + @"SELECT COUNT(*) FROM `Customers` WHERE `City` = {0} AND `ContactTitle` = @contactTitle", city, + contactTitleParameter); + + Assert.Equal(-1, actual); + + actual = async + ? await context.Database.ExecuteSqlRawAsync( + @"SELECT COUNT(*) FROM `Customers` WHERE `City` = @city AND `ContactTitle` = {1}", cityParameter, contactTitle) + : context.Database.ExecuteSqlRaw( + @"SELECT COUNT(*) FROM `Customers` WHERE `City` = @city AND `ContactTitle` = {1}", cityParameter, contactTitle); + + Assert.Equal(-1, actual); AssertSql( $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 255)")} {AssertSqlHelper.Declaration("@contactTitle='Sales Representative' (Nullable = false) (Size = 20)")} -SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@p0")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@contactTitle")}", +SELECT COUNT(*) FROM `Customers` WHERE `City` = {AssertSqlHelper.Parameter("@p0")} AND `ContactTitle` = {AssertSqlHelper.Parameter("@contactTitle")}", // $@"{AssertSqlHelper.Declaration("@city='London' (Nullable = false) (Size = 6)")} {AssertSqlHelper.Declaration("@p0='Sales Representative' (Size = 255)")} -SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@city")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@p0")}"); +SELECT COUNT(*) FROM `Customers` WHERE `City` = {AssertSqlHelper.Parameter("@city")} AND `ContactTitle` = {AssertSqlHelper.Parameter("@p0")}"); } public override async Task Query_with_parameters_interpolated(bool async) { - await base.Query_with_parameters_interpolated(async); + var city = "London"; + var contactTitle = "Sales Representative"; + + using var context = CreateContext(); + + var actual = async + ? await context.Database.ExecuteSqlInterpolatedAsync( + $@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {city} AND `ContactTitle` = {contactTitle}") + : context.Database.ExecuteSqlInterpolated( + $@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {city} AND `ContactTitle` = {contactTitle}"); + + Assert.Equal(-1, actual); AssertSql( $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 255)")} {AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 255)")} -SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@p0")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@p1")}"); +SELECT COUNT(*) FROM `Customers` WHERE `City` = {AssertSqlHelper.Parameter("@p0")} AND `ContactTitle` = {AssertSqlHelper.Parameter("@p1")}"); + } + + public override async Task Query_with_parameters_interpolated_2(bool async) + { + var city = "London"; + var contactTitle = "Sales Representative"; + + using var context = CreateContext(); + + var actual = async + ? await context.Database.ExecuteSqlAsync( + $@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {city} AND `ContactTitle` = {contactTitle}") + : context.Database.ExecuteSql( + $@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {city} AND `ContactTitle` = {contactTitle}"); + + Assert.Equal(-1, actual); } protected override DbParameter CreateDbParameter(string name, object value) @@ -126,9 +214,41 @@ SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter(" return new OdbcParameter { ParameterName = name, Value = value }; } - protected override string TenMostExpensiveProductsSproc => "`Ten Most Expensive Products`"; - protected override string CustomerOrderHistorySproc => "`CustOrderHist` @CustomerID"; - protected override string CustomerOrderHistoryWithGeneratedParameterSproc => "`CustOrderHist` @CustomerID = {0}"; + public override async Task Query_with_DbParameters_interpolated(bool async) + { + var city = CreateDbParameter("city", "London"); + var contactTitle = CreateDbParameter("contactTitle", "Sales Representative"); + + using var context = CreateContext(); + + var actual = async + ? await context.Database.ExecuteSqlInterpolatedAsync( + $@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {city} AND `ContactTitle` = {contactTitle}") + : context.Database.ExecuteSqlInterpolated( + $@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {city} AND `ContactTitle` = {contactTitle}"); + + Assert.Equal(-1, actual); + } + + public override async Task Query_with_DbParameters_interpolated_2(bool async) + { + var city = CreateDbParameter("city", "London"); + var contactTitle = CreateDbParameter("contactTitle", "Sales Representative"); + + using var context = CreateContext(); + + var actual = async + ? await context.Database.ExecuteSqlAsync( + $@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {city} AND `ContactTitle` = {contactTitle}") + : context.Database.ExecuteSql( + $@"SELECT COUNT(*) FROM `Customers` WHERE `City` = {city} AND `ContactTitle` = {contactTitle}"); + + Assert.Equal(-1, actual); + } + + protected override string TenMostExpensiveProductsSproc => "EXEC `Ten Most Expensive Products`"; + protected override string CustomerOrderHistorySproc => "EXEC `CustOrderHist` CustomerID"; + protected override string CustomerOrderHistoryWithGeneratedParameterSproc => "EXEC `CustOrderHist` CustomerID = {0}"; private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Jet.FunctionalTests/Update/NonSharedModelUpdatesJetTest.cs b/test/EFCore.Jet.FunctionalTests/Update/NonSharedModelUpdatesJetTest.cs index 6a15a2c..848d8fc 100644 --- a/test/EFCore.Jet.FunctionalTests/Update/NonSharedModelUpdatesJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Update/NonSharedModelUpdatesJetTest.cs @@ -22,76 +22,79 @@ public class NonSharedModelUpdatesJetTest : NonSharedModelUpdatesTestBase AssertSql( """ -@p0='AC South' (Size = 4000) +@p0='AC South' (Size = 255) -SET IMPLICIT_TRANSACTIONS OFF; -SET NOCOUNT ON; -INSERT INTO [AuthorsClub] ([Name]) -OUTPUT INSERTED.[Id] +INSERT INTO `AuthorsClub` (`Name`) VALUES (@p0); +SELECT `Id` +FROM `AuthorsClub` +WHERE @@ROWCOUNT = 1 AND `Id` = @@identity; """, // """ @p1='1' -@p2='Alice' (Size = 4000) +@p2='Alice' (Size = 255) -SET IMPLICIT_TRANSACTIONS OFF; -SET NOCOUNT ON; -INSERT INTO [Author] ([AuthorsClubId], [Name]) -OUTPUT INSERTED.[Id] +INSERT INTO `Author` (`AuthorsClubId`, `Name`) VALUES (@p1, @p2); +SELECT `Id` +FROM `Author` +WHERE @@ROWCOUNT = 1 AND `Id` = @@identity; """, // """ @p3='1' -@p4=NULL (Size = 4000) +@p4=NULL (Size = 255) -SET IMPLICIT_TRANSACTIONS OFF; -SET NOCOUNT ON; -INSERT INTO [Book] ([AuthorId], [Title]) -OUTPUT INSERTED.[Id] +INSERT INTO `Book` (`AuthorId`, `Title`) VALUES (@p3, @p4); +SELECT `Id` +FROM `Book` +WHERE @@ROWCOUNT = 1 AND `Id` = @@identity; """, // """ -SELECT TOP(2) [b].[Id], [b].[AuthorId], [b].[Title], [a].[Id], [a].[AuthorsClubId], [a].[Name] -FROM [Book] AS [b] -INNER JOIN [Author] AS [a] ON [b].[AuthorId] = [a].[Id] +SELECT TOP 2 `b`.`Id`, `b`.`AuthorId`, `b`.`Title`, `a`.`Id`, `a`.`AuthorsClubId`, `a`.`Name` +FROM `Book` AS `b` +INNER JOIN `Author` AS `a` ON `b`.`AuthorId` = `a`.`Id` """, // """ -@p0='AC North' (Size = 4000) +@p0='AC North' (Size = 255) -SET IMPLICIT_TRANSACTIONS OFF; -SET NOCOUNT ON; -INSERT INTO [AuthorsClub] ([Name]) -OUTPUT INSERTED.[Id] +INSERT INTO `AuthorsClub` (`Name`) VALUES (@p0); +SELECT `Id` +FROM `AuthorsClub` +WHERE @@ROWCOUNT = 1 AND `Id` = @@identity; """, // """ @p1='2' -@p2='Author of the year 2023' (Size = 4000) +@p2='Author of the year 2023' (Size = 255) -SET IMPLICIT_TRANSACTIONS OFF; -SET NOCOUNT ON; -INSERT INTO [Author] ([AuthorsClubId], [Name]) -OUTPUT INSERTED.[Id] +INSERT INTO `Author` (`AuthorsClubId`, `Name`) VALUES (@p1, @p2); +SELECT `Id` +FROM `Author` +WHERE @@ROWCOUNT = 1 AND `Id` = @@identity; """, // """ -@p4='1' @p3='2' -@p5='1' - -SET NOCOUNT ON; -UPDATE [Book] SET [AuthorId] = @p3 -OUTPUT 1 -WHERE [Id] = @p4; -DELETE FROM [Author] -OUTPUT 1 -WHERE [Id] = @p5; +@p4='1' + +UPDATE `Book` SET `AuthorId` = @p3 +WHERE `Id` = @p4; +SELECT @@ROWCOUNT; +""", + // +""" +@p0='1' + +DELETE FROM `Author` +WHERE `Id` = @p0; +SELECT @@ROWCOUNT; """); }