OrmLite support for string extensions

Is there a way to support this kind of scenario with ormlite?

public static class Specific
{
    public static readonly List<string> Prefixes = new() { "eywuyw","hftwrw","irete"};
}

public static class StringExtensions
{
    public static bool StartsWithSpecificPrefix(this string value)
    {
        return Specific.Prefixes.Any(value.StartsWith);
    }
}

var noOfDeletedEntries =
db.Delete<Entries>(x =>
    x.Description.StartsWithSpecificPrefix() &&
    x.Start >= dateRange.Start &&
    x.Start <= dateRange.End
);

This throws System.NotSupportedException: Specified method is not supported.

In the past I’ve been able to use string extensions with EntityFramework using this project https://github.com/hazzik/DelegateDecompiler

It was pretty useful and looked something like this from what I recall:

using (var ctx = new Entities())
{
    var coll = ctx.Entries.Where(x =>

        x.Start >= start &&
        x.Start <= end &&

        x.Description.StartsWithSpecificPrefix()
        
    ).Decompile(); //The call to .Decompile(); uses DelegateDecompiler

    ctx.Entries.RemoveRange(coll);

    ctx.SaveChanges();
}

Is there a way to accomplish this kind of things with OrmLite?

Thanks!

No, that C# Expression is what the LINQ provider analyzes in order to translate it into server side SQL that it executes on the server, it can only support translating analyzable (i.e. non-compiled) expressions it knows about, it wont be able to translate random C# delegates.

The only way you’re going to be able to use a compiled C# delegate is to filter it on an in memory resultset and delete the filtered results, e.g:

var rows = db.Select<Entries>(x =>  x.Start >= date.Start && x.Start <= date.End)
   .Where(x => x.Description.StartsWithSpecificPrefix());

rows.Each(x => db.Delete(x));

However that would be an N+1 operation with 1 DELETE operation performed per result, it would be more efficient to capture all primary keys and delete them in 1 query, e.g:

db.DeleteByIds<Entries>(rows.Map(x => x.Id));

Alternatively you may want to look at constructing a dynamic SQL expression which is much easier than trying to execute compiled C# delegates on the server, e.g:

db.Delete<Person>(where: "Age = @age", new { age = 27 });

1 Like