With EF 6 (and .NET Framework), I was able to map Oracle built in functions by creating a static class like this:
public static class OracleFunctions
{
[Function(FunctionType.BuiltInFunction, "TO_CHAR")]
public static string ToChar(this decimal? value) => Function.CallNotSupported<string>();
[Function(FunctionType.BuiltInFunction, "LENGTHB")]
public static int? LENGTHB(this byte[] value) => Function.CallNotSupported<int?>();
}
And then I added this code to OnModelCreating
:
modelBuilder.Conventions.Add(new FunctionConvention(typeof(OracleFunctions)));
However, this syntax does not work for EF Core. I attempted to create a similar static class:
public static class OracleFunctions
{
public static int LENGTHB(this byte[] input)
{
throw new NotSupportedException("This function can only be used in LINQ to Entities queries.");
}
public static string ToChar(this decimal? value)
{
throw new NotSupportedException("This function can only be used in LINQ to Entities queries.");
}
}
And added them in OnModelCreating
:
modelBuilder.HasDbFunction(typeof(OracleFunctions).GetMethod(nameof(OracleFunctions.LENGTHB)))
.HasName("LENGTHB");
modelBuilder.HasDbFunction(typeof(OracleFunctions).GetMethod(nameof(OracleFunctions.ToChar)))
.HasName("TO_CHAR");
Using the functions like this:
var bar = dbContext.WORKFLOW_DOCUMENT.Where(x => OracleFunctions.LENGTHB(x.Template) > 0).FirstOrDefault();
But it results in the following error:
Oracle.ManagedDataAccess.Client.OracleException: 'ORA-00904: "MySchema"."LENGTHB": invalid identifier https://docs.oracle.com/error-help/db/ora-00904/'
Schema doesn't matter for built-in functions, but you have to tell EF that your function is built-in (by default it is assumed to be user-defined). You do that by ... well, using the surprisingly named IsBuiltIn
method of the DbFunctionBuilder
class returned by the all HasDbFunction
fluent API. e.g.
modelBuilder.HasDbFunction(typeof(OracleFunctions).GetMethod(nameof(OracleFunctions.LENGTHB)))
.HasName("LENGTHB")
.IsBuiltIn(); // <--
As you can see, the class has many other methods (HasSchema
, HasParameter
, HasStoreType
, IsNullable
and even HasTranslation
) which allow you to configure all aspects of the function mapping, not just the name.
DbFunction
attribute also has some properties (IsBuiltIn
, IsNullable
, Name
, Schema
), but is not so flexible as the fluent API.