diff --git a/README.md b/README.md index 2d8f012..a07fdb4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ View Entity Framework Core query plan directly inside Visual Studio. ## Introduction -With Entity Framework Core query plan debugger visualizer, you can view the query plan of your queries directly inside Visual Studio. Currently, the visualizer supports SQL Server and PostgreSQL. +With Entity Framework Core query plan debugger visualizer, you can view the query plan of your queries directly inside Visual Studio. Currently, the visualizer supports SQL Server, PostgreSQL and Oracle. > [!IMPORTANT] > The visualizer requires **Visual Studio Version 17.9.0 ([Released on February 13th](https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-9-now-available/)) or newer** and supports **EF Core 7 or newer**. @@ -36,6 +36,10 @@ Click on 'Query Plan Visualizer' and the query plan will be displayed for your q ![PostgreSQL Plan](doc/PostgreSQLPlan1.png) +### Oracle: + +![Oracle Plan](doc/OraclePlan.png) + ## Known Issues: - If query plan extraction takes more than 5 seconds, you will get [Evaluation timed out error](https://github.com/Giorgi/EFCore.Visualizer/issues/25) diff --git a/doc/OraclePlan.png b/doc/OraclePlan.png new file mode 100644 index 0000000..360c909 Binary files /dev/null and b/doc/OraclePlan.png differ diff --git a/src/EFCore.Visualizer/EFCore.Visualizer.csproj b/src/EFCore.Visualizer/EFCore.Visualizer.csproj index db21671..6eb2dbf 100644 --- a/src/EFCore.Visualizer/EFCore.Visualizer.csproj +++ b/src/EFCore.Visualizer/EFCore.Visualizer.csproj @@ -11,6 +11,7 @@ + @@ -54,6 +55,9 @@ true + + true + diff --git a/src/EFCore.Visualizer/Resources/Oracle/template.html b/src/EFCore.Visualizer/Resources/Oracle/template.html new file mode 100644 index 0000000..d1ad284 --- /dev/null +++ b/src/EFCore.Visualizer/Resources/Oracle/template.html @@ -0,0 +1,95 @@ + + + + + + Query and Execution Plan + + + + +
+
+

+        
+ +
+ +
+

+        
+
+ + + + + diff --git a/src/EFCore.Visualizer/source.extension.vsixmanifest b/src/EFCore.Visualizer/source.extension.vsixmanifest index b0e584f..df8f706 100644 --- a/src/EFCore.Visualizer/source.extension.vsixmanifest +++ b/src/EFCore.Visualizer/source.extension.vsixmanifest @@ -8,7 +8,7 @@ https://github.com/Giorgi/EFCore.Visualizer https://github.com/Giorgi/EFCore.Visualizer/blob/main/README.md#usage Images\IconSmall.png - EFCore, SQL Server, PostgreSQL, Visualizer, Query Plan + EFCore, SQL Server, PostgreSQL, Oracle, Visualizer, Query Plan diff --git a/src/IQueryableObjectSource/DatabaseProvider.cs b/src/IQueryableObjectSource/DatabaseProvider.cs index 8c2a460..d700209 100644 --- a/src/IQueryableObjectSource/DatabaseProvider.cs +++ b/src/IQueryableObjectSource/DatabaseProvider.cs @@ -83,4 +83,24 @@ protected override string ExtractPlanInternal(DbCommand command) } internal override string GetPlanDirectory(string baseDirectory) => Path.Combine(baseDirectory, "Postgres"); +} + +class OracleDatabaseProvider(DbCommand command) : DatabaseProvider(command) +{ + protected override string ExtractPlanInternal(DbCommand command) + { + command.CommandText = "EXPLAIN PLAN FOR " + command.CommandText; + command.ExecuteNonQuery(); + + // Querying the execution plan using DBMS_XPLAN + command.CommandText = "SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY())"; + using var reader = command.ExecuteReader(); + + // Fetching the plan output + var plan = string.Join(Environment.NewLine, reader.Cast().Select(r => r.GetString(0))); + + return plan; + } + + internal override string GetPlanDirectory(string baseDirectory) => Path.Combine(baseDirectory, "Oracle"); } \ No newline at end of file diff --git a/src/IQueryableObjectSource/EFCoreQueryableObjectSource.cs b/src/IQueryableObjectSource/EFCoreQueryableObjectSource.cs index e5c9cdb..7763ba0 100644 --- a/src/IQueryableObjectSource/EFCoreQueryableObjectSource.cs +++ b/src/IQueryableObjectSource/EFCoreQueryableObjectSource.cs @@ -77,6 +77,7 @@ private static DatabaseProvider GetDatabaseProvider(DbCommand command) { "Microsoft.Data.SqlClient.SqlCommand" => new SqlServerDatabaseProvider(command), "Npgsql.NpgsqlCommand" => new PostgresDatabaseProvider(command), + "Oracle.ManagedDataAccess.Client.OracleCommand" => new OracleDatabaseProvider(command), _ => null }; }