diff --git a/EntityFrameworkCore.Jet.sln b/EntityFrameworkCore.Jet.sln index 1710d69..d9054f7 100644 --- a/EntityFrameworkCore.Jet.sln +++ b/EntityFrameworkCore.Jet.sln @@ -46,6 +46,13 @@ EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCore.Jet.Tests", "test\EFCore.Jet.Tests\EFCore.Jet.Tests.csproj", "{770A076B-A448-499C-BB86-A37994C04523}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JetProviderExceptionTests", "test\JetProviderExceptionTests\JetProviderExceptionTests.csproj", "{5CD8B47D-E32C-480A-8331-55549EC8E12E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{84E4151A-DA0B-43C0-B1DD-F027241FE49F}" +ProjectSection(SolutionItems) = preProject + tools\Resources.tt = tools\Resources.tt +EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -66,8 +73,8 @@ Global {88BE8B4F-8DA9-42B9-9A1F-839451BA5F8C}.Release|Any CPU.Build.0 = Release|Any CPU {88BE8B4F-8DA9-42B9-9A1F-839451BA5F8C}.Release|x64.ActiveCfg = Release|x64 {88BE8B4F-8DA9-42B9-9A1F-839451BA5F8C}.Release|x64.Build.0 = Release|x64 - {88BE8B4F-8DA9-42B9-9A1F-839451BA5F8C}.Release|x86.ActiveCfg = Release|Any CPU - {88BE8B4F-8DA9-42B9-9A1F-839451BA5F8C}.Release|x86.Build.0 = Release|Any CPU + {88BE8B4F-8DA9-42B9-9A1F-839451BA5F8C}.Release|x86.ActiveCfg = Release|x86 + {88BE8B4F-8DA9-42B9-9A1F-839451BA5F8C}.Release|x86.Build.0 = Release|x86 {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Debug|Any CPU.Build.0 = Debug|Any CPU {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Debug|x64.ActiveCfg = Debug|x64 @@ -78,8 +85,8 @@ Global {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Release|Any CPU.Build.0 = Release|Any CPU {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Release|x64.ActiveCfg = Release|x64 {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Release|x64.Build.0 = Release|x64 - {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Release|x86.ActiveCfg = Release|Any CPU - {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Release|x86.Build.0 = Release|Any CPU + {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Release|x86.ActiveCfg = Release|x86 + {E77112B7-B6BA-43A8-B21F-DD79A7A47A2F}.Release|x86.Build.0 = Release|x86 {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Debug|x64.ActiveCfg = Debug|x64 @@ -90,8 +97,8 @@ Global {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Release|Any CPU.Build.0 = Release|Any CPU {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Release|x64.ActiveCfg = Release|x64 {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Release|x64.Build.0 = Release|x64 - {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Release|x86.ActiveCfg = Release|Any CPU - {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Release|x86.Build.0 = Release|Any CPU + {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Release|x86.ActiveCfg = Release|x86 + {D6966B04-4C38-4925-BCDE-F8655F38D04C}.Release|x86.Build.0 = Release|x86 {50CA2970-B995-4D28-9F6C-F7CA4940F23A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {50CA2970-B995-4D28-9F6C-F7CA4940F23A}.Debug|Any CPU.Build.0 = Debug|Any CPU {50CA2970-B995-4D28-9F6C-F7CA4940F23A}.Debug|x64.ActiveCfg = Debug|x64 @@ -114,8 +121,8 @@ Global {3C88D49A-7EF2-42BA-A8D7-9DF7D358FD24}.Release|Any CPU.Build.0 = Release|Any CPU {3C88D49A-7EF2-42BA-A8D7-9DF7D358FD24}.Release|x64.ActiveCfg = Release|x64 {3C88D49A-7EF2-42BA-A8D7-9DF7D358FD24}.Release|x64.Build.0 = Release|x64 - {3C88D49A-7EF2-42BA-A8D7-9DF7D358FD24}.Release|x86.ActiveCfg = Release|Any CPU - {3C88D49A-7EF2-42BA-A8D7-9DF7D358FD24}.Release|x86.Build.0 = Release|Any CPU + {3C88D49A-7EF2-42BA-A8D7-9DF7D358FD24}.Release|x86.ActiveCfg = Release|x86 + {3C88D49A-7EF2-42BA-A8D7-9DF7D358FD24}.Release|x86.Build.0 = Release|x86 {770A076B-A448-499C-BB86-A37994C04523}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {770A076B-A448-499C-BB86-A37994C04523}.Debug|Any CPU.Build.0 = Debug|Any CPU {770A076B-A448-499C-BB86-A37994C04523}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -128,6 +135,18 @@ Global {770A076B-A448-499C-BB86-A37994C04523}.Release|x64.Build.0 = Release|Any CPU {770A076B-A448-499C-BB86-A37994C04523}.Release|x86.ActiveCfg = Release|Any CPU {770A076B-A448-499C-BB86-A37994C04523}.Release|x86.Build.0 = Release|Any CPU + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Release|Any CPU.Build.0 = Release|Any CPU + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Debug|x64.ActiveCfg = Debug|x64 + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Debug|x64.Build.0 = Debug|x64 + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Debug|x86.ActiveCfg = Debug|x86 + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Debug|x86.Build.0 = Debug|x86 + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Release|x64.ActiveCfg = Release|x64 + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Release|x64.Build.0 = Release|x64 + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Release|x86.ActiveCfg = Release|x86 + {5CD8B47D-E32C-480A-8331-55549EC8E12E}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -139,6 +158,7 @@ Global {50CA2970-B995-4D28-9F6C-F7CA4940F23A} = {6A8DE399-1804-4113-A408-F23B7F5C9CAC} {3C88D49A-7EF2-42BA-A8D7-9DF7D358FD24} = {6A8DE399-1804-4113-A408-F23B7F5C9CAC} {770A076B-A448-499C-BB86-A37994C04523} = {6A8DE399-1804-4113-A408-F23B7F5C9CAC} + {5CD8B47D-E32C-480A-8331-55549EC8E12E} = {6A8DE399-1804-4113-A408-F23B7F5C9CAC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9359773D-6399-447E-9814-6CB41C2FB664} diff --git a/test/JetProviderExceptionTests/IceCreamTest.cs b/test/JetProviderExceptionTests/IceCreamTest.cs new file mode 100644 index 0000000..c475202 --- /dev/null +++ b/test/JetProviderExceptionTests/IceCreamTest.cs @@ -0,0 +1,100 @@ +using System; +using System.Data.Jet; +using System.Data.Odbc; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace JetProviderExceptionTests +{ + public class IceCreamTest + { + public class IceCream + { + public int IceCreamId { get; set; } + public string Name { get; set; } + public string Brand { get; set; } + public DateTime? BestServedBefore { get; set; } + } + + public class Context : DbContext + { + public DbSet IceCreams { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder + // .UseJet("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=JetProviderExceptionTests.accdb") + .UseJet( + JetConnection.GetConnectionString("JetProviderExceptionTests.accdb", OdbcFactory.Instance), + OdbcFactory.Instance) + .UseLoggerFactory( + LoggerFactory.Create( + b => b + .AddConsole() + .AddFilter(level => level >= LogLevel.Information))) + .EnableSensitiveDataLogging() + .EnableDetailedErrors(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + var today = DateTime.Today; + + modelBuilder.Entity() + .HasData( + new IceCream {IceCreamId = 1, Name = "Vanilla", Brand = "Ben & Jerry", BestServedBefore = today.AddDays(180)}, + new IceCream {IceCreamId = 2, Name = "Chocolate", Brand = "Baskin-Robbins", BestServedBefore = today.AddDays(210)}, + new IceCream {IceCreamId = 3, Name = "Strawberry", Brand = "Dairy Queen", BestServedBefore = today.AddDays(90)}, + new IceCream {IceCreamId = 4, Name = "Matcha", Brand = "Kikyouya", BestServedBefore = today.AddDays(150)} + ); + } + } + + public void Run() + { + try + { + using (var context = new Context()) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + } + + for (var i = 0; i < 1024; i++) + { + var today = DateTime.Today; + var from = today.AddDays(110); + + using var context = new Context(); + + var query1 = context.IceCreams + .Where(c => c.Name == "Vanilla") + .Select(c => c.Brand) + .Union( + context.IceCreams + .Where(c => c.BestServedBefore > from) + .Select(c => c.Brand)) + .ToList(); + + var boolean = false; + + var query2 = context.IceCreams + .Select(c => new {f = boolean}) + .ToList(); + + boolean = true; + + var query3 = context.IceCreams + .Select(c => new {f = boolean}) + .ToList(); + } + } + catch (AccessViolationException e) + { + Console.WriteLine(e); + throw; + } + } + } +} \ No newline at end of file diff --git a/test/JetProviderExceptionTests/JetProviderExceptionTests.csproj b/test/JetProviderExceptionTests/JetProviderExceptionTests.csproj new file mode 100644 index 0000000..01dd16a --- /dev/null +++ b/test/JetProviderExceptionTests/JetProviderExceptionTests.csproj @@ -0,0 +1,63 @@ + + + + Exe + netcoreapp3.1 + AnyCPU;x86;x64 + + + + + + + + + + + + + + + + + + $(LocalEFCoreRepository)\artifacts\bin\EFCore.Relational.Specification.Tests\Debug\$(TargetFramework)\Microsoft.EntityFrameworkCore.dll + + + $(LocalEFCoreRepository)\artifacts\bin\EFCore.Relational.Specification.Tests\Debug\$(TargetFramework)\Microsoft.EntityFrameworkCore.Abstractions.dll + + + $(LocalEFCoreRepository)\artifacts\bin\EFCore.Relational.Specification.Tests\Debug\$(TargetFramework)\Microsoft.EntityFrameworkCore.Analyzers.dll + + + $(LocalEFCoreRepository)\artifacts\bin\EFCore.Design\Debug\$(DefaultNetStandardTargetFramework)\Microsoft.EntityFrameworkCore.Design.dll + + + $(LocalEFCoreRepository)\artifacts\bin\EFCore.Relational.Specification.Tests\Debug\$(TargetFramework)\Microsoft.EntityFrameworkCore.Proxies.dll + + + $(LocalEFCoreRepository)\artifacts\bin\EFCore.Relational.Specification.Tests\Debug\$(TargetFramework)\Microsoft.EntityFrameworkCore.Relational.dll + + + $(LocalEFCoreRepository)\artifacts\bin\EFCore.Relational.Specification.Tests\Debug\$(TargetFramework)\Microsoft.EntityFrameworkCore.Relational.Specification.Tests.dll + + + $(LocalEFCoreRepository)\artifacts\bin\EFCore.Relational.Specification.Tests\Debug\$(TargetFramework)\Microsoft.EntityFrameworkCore.Specification.Tests.dll + + + + + + + + + + + + + + Always + + + + diff --git a/test/JetProviderExceptionTests/Northwind.accdb b/test/JetProviderExceptionTests/Northwind.accdb new file mode 100644 index 0000000..b24fa11 Binary files /dev/null and b/test/JetProviderExceptionTests/Northwind.accdb differ diff --git a/test/JetProviderExceptionTests/Northwind.zip b/test/JetProviderExceptionTests/Northwind.zip new file mode 100644 index 0000000..e95fbfc Binary files /dev/null and b/test/JetProviderExceptionTests/Northwind.zip differ diff --git a/test/JetProviderExceptionTests/NorthwindTestEFCore.cs b/test/JetProviderExceptionTests/NorthwindTestEFCore.cs new file mode 100644 index 0000000..888bd45 --- /dev/null +++ b/test/JetProviderExceptionTests/NorthwindTestEFCore.cs @@ -0,0 +1,92 @@ +using System; +using System.Data.Jet; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace JetProviderExceptionTests +{ + public class NorthwindTestEFCore + { + public class Customer + { + public string CustomerID { get; set; } + public string CompanyName { get; set; } + public string ContactName { get; set; } + public string ContactTitle { get; set; } + public string Address { get; set; } + public string City { get; set; } + public string Region { get; set; } + public string PostalCode { get; set; } + public string Country { get; set; } + public string Phone { get; set; } + public string Fax { get; set; } + } + + public class Context : DbContext + { + public DbSet Customers { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder + .UseJet("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Northwind.accdb", JetConfiguration.DefaultProviderFactory) + .UseLoggerFactory( + LoggerFactory.Create( + b => b + .AddConsole() + .AddFilter(level => level >= LogLevel.Information))) + .EnableSensitiveDataLogging() + .EnableDetailedErrors(); + } + } + + public void Run() + { + try + { + for (var i = 0; i < 100; i++) + { + using var context = new Context(); + + for (var j = 0; j < 12; j++) + { + // + // Select_Union: + // + + var query1 = context.Set() + .Where(c => c.City == "Berlin") + .Select(c => c.Address) + .Union( + context.Set() + .Where(c => c.City == "London") + .Select(c => c.Address)) + .ToList(); + + // + // Select_bool_closure: + // + + var boolean = false; + + var query2 = context.Set() + .Select(c => new {f = boolean}) + .ToList(); + + boolean = true; + + var query3 = context.Set() + .Select(c => new {f = boolean}) + .ToList(); + } + } + } + catch (AccessViolationException e) + { + Console.WriteLine(e); + throw; + } + } + } +} \ No newline at end of file diff --git a/test/JetProviderExceptionTests/NorthwindTestJetCommand.cs b/test/JetProviderExceptionTests/NorthwindTestJetCommand.cs new file mode 100644 index 0000000..db9aefc --- /dev/null +++ b/test/JetProviderExceptionTests/NorthwindTestJetCommand.cs @@ -0,0 +1,69 @@ +using System; +using System.Data.Jet; + +namespace JetProviderExceptionTests +{ + public class NorthwindTestJetCommand + { + public void Run() + { + try + { + for (var i = 0; i < 100; i++) + { + using var connection = new JetConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Northwind.accdb"); + connection.Open(); + + for (var j = 0; j < 2000; j++) + { + Console.WriteLine($"{i:00}: {j:000}"); + + // + // Select_Union: + // + + using (var command1 = connection.CreateCommand()) + { + command1.CommandText = @"SELECT `c`.`Address` +FROM `Customers` AS `c` +WHERE `c`.`City` = 'Berlin' +UNION +SELECT `c0`.`Address` +FROM `Customers` AS `c0` +WHERE `c0`.`City` = 'London'"; + + using (var dataReader1 = command1.ExecuteReader()) + { + while (dataReader1.Read()) + { + } + } + } + + // + // Select_bool_closure: + // + + using (var command2 = connection.CreateCommand()) + { + command2.CommandText = @"SELECT 1 +FROM `Customers` AS `c`"; + + using (var dataReader2 = command2.ExecuteReader()) + { + while (dataReader2.Read()) + { + } + } + } + } + } + } + catch (AccessViolationException e) + { + Console.WriteLine(e); + Console.ReadKey(true); + } + } + } +} \ No newline at end of file diff --git a/test/JetProviderExceptionTests/NorthwindTestOleDbCommand.cs b/test/JetProviderExceptionTests/NorthwindTestOleDbCommand.cs new file mode 100644 index 0000000..a0f7538 --- /dev/null +++ b/test/JetProviderExceptionTests/NorthwindTestOleDbCommand.cs @@ -0,0 +1,81 @@ +using System; +using System.Data.OleDb; + +namespace JetProviderExceptionTests +{ + public class NorthwindTestOleDbCommand + { + public void Run() + { + try + { + using var connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.16.0;Data Source=Northwind.accdb"); + connection.Open(); + + for (var i = 0; i < 1000; i++) + { + Console.WriteLine($"{i:000}"); + + // + // Select_Union: + // + + using (var command1 = connection.CreateCommand()) + { + command1.CommandText = @"SELECT `c`.`Address` +FROM `Customers` AS `c` +WHERE `c`.`City` = 'Berlin' +UNION +SELECT `c0`.`Address` +FROM `Customers` AS `c0` +WHERE `c0`.`City` = 'London'"; + + using (var dataReader1 = command1.ExecuteReader()) + { + while (dataReader1.Read()) + { + } + } + } + + /* + using (var command15 = connection.CreateCommand()) + { + command15.CommandText = @"SELECT [c].[Address] +FROM [Customers] AS [c] +WHERE [c].[City] = 'Madrid'"; + + using (var dataReader15 = command15.ExecuteReader()) + { + while (dataReader15.Read()) + { + } + } + } + */ + + // + // Select_bool_closure: + // + + using (var command2 = connection.CreateCommand()) + { + command2.CommandText = @"SELECT 1 +FROM `Customers` AS `c`"; + + using (var dataReader2 = command2.ExecuteReader()) + { + while (dataReader2.Read()) + { + } + } + } + } + } + catch (AccessViolationException e) + { + Console.WriteLine(e); + } + } + } +} \ No newline at end of file diff --git a/test/JetProviderExceptionTests/Program.cs b/test/JetProviderExceptionTests/Program.cs new file mode 100644 index 0000000..f4f7b23 --- /dev/null +++ b/test/JetProviderExceptionTests/Program.cs @@ -0,0 +1,32 @@ +using System; + +namespace JetProviderExceptionTests +{ + internal static class Program + { + private static void Main() + { + Console.WriteLine($"Running as {(Environment.Is64BitProcess ? "x64" : "x86")} process."); + + var tagDBPARAMBINDINFOName = "tagDBPARAMBINDINFO" + (Environment.Is64BitProcess + ? string.Empty + : "_x86"); + + // Is 2 on x86 and 8 on x64. + Console.WriteLine($"{tagDBPARAMBINDINFOName} field alignment is {Type.GetType($"System.Data.OleDb.{tagDBPARAMBINDINFOName}, System.Data.OleDb").StructLayoutAttribute.Pack}."); + + // Is 8 on both x86 and x64. + Console.WriteLine($"tagDBPARAMS field alignment is {Type.GetType("System.Data.OleDb.tagDBPARAMS, System.Data.OleDb").StructLayoutAttribute.Pack}."); + + Console.WriteLine(); + //Console.WriteLine("Press any key to start..."); + //Console.ReadKey(); + + //var northwindTest = new NorthwindTestOleDbCommand(); + //northwindTest.Run(); + + var iceCreamTest = new IceCreamTest(); + iceCreamTest.Run(); + } + } +} \ No newline at end of file