I'm using EF Core 8 with an Oracle database.
I'm trying to do a select of data where a value is contained in a column. The SQL statement would be like :
SELECT *
FROM TASKS
WHERE NAME LIKE "%Task%"
I have the following linq code (Name
is a ValueObject
of type string):
List<TaskEntity> tasks = await _dbSet.Where(x => x.Name.Value.Contains("Task"))
.ToListAsync();
And the entity
public partial class TaskEntity
{
public DatabaseTableId Id { get; set; }
public Name Name { get; set; }
}
But I'm getting this error:
System.InvalidOperationException: 'The LINQ expression
'DbSet()
.Where(t => t.Name.Value.Contains("Task"))' could not be translated.
The model builder:
modelBuilder.Entity<TaskEntity>(entity =>
{
entity.HasKey(e => e.Id);
entity.ToTable("TASKS");
entity.Property(e => e.Id)
.HasConversion<DatabaseTableIdConverter>()
.ValueGeneratedOnAdd()
.HasColumnType("NUMBER")
.HasColumnName("ID");
entity.Property(e => e.Name)
.HasConversion<NameConverter>()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnName("NAME");
});
Name VO (simplified):
public class Name
{
public string Value { get; }
public Name(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentNullException(nameof(Name), "Name cannot be null or empty.");
}
Value = value;
}
}
Name converter:
public class NameConverter : ValueConverter<Name, string>
{
/// <summary>
/// Converts a <see cref="Name"/> to a <see cref="string"/> value to use it in EF
/// </summary>
public NameConverter() : base
(
Name => Name.Value,
value => new Name(value))
{ }
}
I've tried everything, a contains method in the valueobject using EF.Function.Like
... with FromSqlRaw
does work but I need the IQueryable
.
You can enhance your Name
class by adding implicit conversion operators:
public class Name
{
public string Value { get; }
public Name(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentNullException(nameof(Name), "Name cannot be null or empty.");
}
Value = value;
}
public static implicit operator string(Name name) => name.Value;
public static implicit operator Name(string value) => new Name(value);
}
This allows you to use explicit casting when querying:
List<TaskEntity> tasks = await _dbSet
.Where(x => ((string)x.Name).Contains("Task"))
.ToListAsync();
This has been tested with EF Core 8.