Oracle Data Provider for .NET (ODP.NET) Entity Framework Core for Oracle Database.
$ dotnet add package Oracle.EntityFrameworkCore
Release Notes for Oracle Entity Framework Core 10 NuGet Package
January 2026
Oracle Data Provider for .NET (ODP.NET) Entity Framework (EF) Core is a database provider that allows Entity Framework Core to be used with Oracle databases. EF Core is a cross-platform Microsoft object-relational mapper that enables .NET developers to work with relational databases using .NET objects.
This document provides information that supplements the ODP.NET Entity Framework Core documentation.
modelBuilder.Entity<Blog>()
.HasIndex(b => b.Url)
.HasFilter("Url is not null");
// C# - computed columns code sample
modelBuilder.Entity<Blog>()
.Property(b => b.BlogOwner)
.HasComputedColumnSql("\"LastName\" || '','' || \"FirstName\"");
modelBuilder.Entity<Person>()
.UpdateUsingStoredProcedure(
"People_Update",
storedProcedureBuilder =>
{
storedProcedureBuilder.HasRowsAffectedReturnValue(true)
});
public class MyTable
{
public int Id { get; set; }
public int? Value { get; set; }
}
The following LINQ will not work against Oracle Database 21c or lower:
var query = from t in context.Table
group t.Id by t.Value
into tg
select new
{
A = tg.Key,
B = context.Table.Where(t => t.Value == tg.Max() * 6).Max(t => (int?)t.Id)
};
This is due to LINQ creating the following SQL query:
SELECT "t"."Value" "A", "t"."Id", (
SELECT MAX("t0"."Id")
FROM "MyTable" "t0"
WHERE (("t0"."Value" = "t"."Id") OR ("t0"."Value" IS NULL AND MAX("t"."Id") IS NULL))) "B"
FROM "MyTable" "t"
GROUP BY "t"."Value"
The issue is because the inner select query uses a MAX function which refers to a column from the outer select query. Also the way in which the MAX function is used within the WHERE clause is not supported in Oracle Database. The same issue is also applicable when the MIN function is used.
public class Blog
{
public int Id { get; private set; }
public string Name { get; set; }
public List<Post> Posts { get; } = new();
}
public class Post
{
public int Id { get; private set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime PublishedOn { get; set; }
}
Trying to update the Blog.Name using below LINQ would throw 'ORA-00933: SQL command not properly ended'
var query = from blog in context.Set<Blog>().Where(c => c.Name == "MyBlog")
join post in context.Set<Post>().Where(p => p.Title == "Oracle")
on blog.Name equals post.Title
select new { blog, post };
var updateQuery = query.ExecuteUpdate(s => s.SetProperty(c => c.blog.Name, "Updated"));
This is due to LINQ creating the following SQL query, which Oracle database does not support.
UPDATE "Blogs" "b"
SET "b"."Name" = N'Updated'
FROM (
SELECT "p"."Id", "p"."BlogId", "p"."Content", "p"."PublishedOn", "p"."Title"
FROM "Posts" "p"
WHERE "p"."Title" = N'Oracle') "t"
WHERE (("b"."Name" = "t"."Title") AND ("b"."Name" = N'MyBlog'))
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public DateTimeOffset Timeline { get; set; }
}
The following LINQ will not work:
var timeSpan = new TimeSpan(1000);
var authorsInChigley1 = context.Authors.Where(e => e.Timeline > DateTimeOffset.Now - timeSpan).ToQueryString();
Following is the PL/SQL that gets generated.
DECLARE
l_sql varchar2(32767);
l_cur pls_integer;
l_execute pls_integer;
BEGIN
l_cur := dbms_sql.open_cursor;
l_sql := 'SELECT "a"."Id", "a"."Name", "a"."Timeline"
FROM "Authors" "a"
WHERE "a"."Timeline" > (SYSDATE - :timeSpan_0)';
dbms_sql.parse(l_cur, l_sql, dbms_sql.native);
dbms_sql.bind_variable(l_cur, ':timeSpan_0', INTERVAL '0 0:0:0.0001000' DAY(8) TO SECOND(7));
l_execute:= dbms_sql.execute(l_cur);
dbms_sql.return_result(l_cur);
END;
Copyright (c) 2025, 2026, Oracle and/or its affiliates.