sql-serverpostgresqllinq2db

linq2db. fallback for provider specific function


I'm using Linq-to-DB (linq2db, linq2db.EntityFrameworkCore).

My software supports several database providers (SQL Server, PostgreSQL). There is a case when I need to use a provider specific function for SQL Server, and for PostgreSQL use an alternative option, or ignore it.

For example, I need this code to work with two providers.

In the case of SQL Server, the ISJSON must be performed, and in the case of PostgreSQL, it must be ignored:

var d1 = db.Invoice
           .Where(i => SqlFn.IsJson(i.InvoiceState) == true)
           .ToLinqToDB().ToList();

Now in the case of PostgreSQL I get an error

'IsJson(i.InvoiceState)' cannot be converted to SQL

How to do this correctly?


Solution

  • You can create other function which handles other providers:

    public static class DbFunctions
    {
        [ExpressionMethod(ProviderName.SqlServer, nameof(SqlServerIsJson))]
        [ExpressionMethod(nameof(EmptyIsJson))]
        [return: NotNullIfNotNull(nameof(expression))]
        public static bool? IsJson(string? expression)
        {
            throw new InvalidOperationException($"'{nameof(IsJson)}' is a server side only function.");
        }
        
        static Expression<Func<string?, bool?>> SqlServerIsJson()
            => e => SqlFn.IsJson(e);
    
        static Expression<Func<string?, bool?>> EmptyIsJson()
            => e => false;
    }
    

    And use in your queries:

    var d1 = db.Invoice
               .Where(i => DbFunctions.IsJson(i.InvoiceState) == true)
               .ToLinqToDB().ToList();