What is the equivalent of the following statement in EF Core?
SqlFunctions.DatePart("week", x.MyDate)
EF.Functions
doesn't seem to have a DatePart
method.
Note that for a single row, EF Core is slower than EF6 unless using context pooling; this could be the cost of setting up all the scoped services for each instance (which isn't done when context pooling is on). For multiple rows, EF Core batches and EF6 doesn't, so EF Core quickly becomes much faster.
EF 6 is a stable and mature ORM while EF Core is relatively new. Microsoft rebuilt EF Core from the ground up and removed many of the internal dependencies and providers that EF 6 had (like SQLClient). In the long run, that will make EF Core much more extensible and lighter weight.
Npgsql Entity Framework Core provider for PostgreSQL EntityFrameworkCore. PostgreSQL is the open source EF Core provider for PostgreSQL. It allows you to interact with PostgreSQL via the most widely-used .
EF Core 7.0 (EF7) adds support for mapping aggregate types to JSON documents stored in “JSON columns” of a relational database. This allows relational databases to directly store documents while retaining the overall relational structure of the data.
It is possible to make use of the datepart SQL function by wrapping it with the DbFunctionAttribute. Tricky part is to tell ef core not to handle the datepart type parameter as a string. Example:
DbContext ef core <= 2.1
:
public int? DatePart(string datePartArg, DateTime? date) => throw new Exception();
public void OnModelCreating(DbModelBuilder modelBuilder) {
var methodInfo = typeof(DbContext).GetRuntimeMethod(nameof(DatePart), new[] { typeof(string), typeof(DateTime) });
modelBuilder
.HasDbFunction(methodInfo)
.HasTranslation(args => new SqlFunctionExpression(nameof(DatePart), typeof(int?), new[]
{
new SqlFragmentExpression(args.ToArray()[0].ToString()),
args.ToArray()[1]
}));
}
DbContext ef core >= 3.1
(static SqlFunctionExpression.Create
call instead of ctor):
public int? DatePart(string datePartArg, DateTime? date) => throw new Exception();
public void OnModelCreating(DbModelBuilder modelBuilder) {
var methodInfo = typeof(DbContext).GetRuntimeMethod(nameof(DatePart), new[] { typeof(string), typeof(DateTime) });
modelBuilder
.HasDbFunction(methodInfo)
.HasTranslation(args => SqlFunctionExpression.Create(nameof(DatePart), new[]
{
new SqlFragmentExpression(args.ToArray()[0].ToString()),
args.ToArray()[1]
}, typeof(int?), null));
}
Query:
repository.Where(x => dbContext.DatePart("week", x.CreatedAt) > 10);
some more info: https://github.com/aspnet/EntityFrameworkCore/issues/10404
watch out not to call the DbFunction method on an interface of DbContext. The call must happend directly on the DbContext instance.
Edit: for ef core 3.1
you can use the static method SqlFunctionExpression.Create
instead of the ctor:
For EF Core 5, it's even different as the SqlFunctionExpression.Create
factory is now obsolete and the SqlFunctionExpression
construction should be used instead. Here's the updated code (if adding it to the DB Context):
public partial class ApplicationDbContext : DbContext
{
public int? DatePart(string datePartArg, DateTimeOffset? date) => throw new InvalidOperationException($"{nameof(DatePart)} cannot be called client side.");
protected override void OnModelCreating(ModelBuilder builder)
{
var methodInfo = typeof(DbFunctionExtensions).GetMethod(nameof(DatePart));
var datePartMethodInfo = typeof(ApplicationDbContext) // Your DB Context
.GetRuntimeMethod(nameof(ApplicationDbContext.DatePart), new[] { typeof(string), typeof(DateTimeOffset) });
builder.HasDbFunction(datePartMethodInfo)
.HasTranslation(args =>
new SqlFunctionExpression("DATEPART",
new[]
{
new SqlFragmentExpression((args.ToArray()[0] as SqlConstantExpression).Value.ToString()),
args.ToArray()[1]
},
true,
new[] { false, false },
typeof(int?),
null
)
);
}
}
Note: You can switch to DateTime
instead of DateTimeOffset
as per your needs.
(The exception has nothing to do with EF Core 5, it's just more clear for anybody working on the code later on or trying to call the method client side).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With