کوئری نویسی در EF Core - قسمت ششم - کار با تاریخ و زمان
نویسنده: وحید نصیری
تاریخ: ۱۳۹۹/۰۵/۱۱ ۱۰:۱۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
var items = context.Bookings
.Where(booking => booking.StartTime.Year == 2012)
.Select(booking => new
{
booking.StartTime.Year,
booking.StartTime.Month,
DaysInMonth = EF.Functions.DateDiffDay(
booking.StartTime.Date.AddDays(1 - booking.StartTime.Date.Day),
booking.StartTime.Date.AddDays(1 - booking.StartTime.Date.Day).AddMonths(1)
)
})
.Distinct()
.OrderBy(r => r.Year)
.ThenBy(r => r.Month)
.ToList();
var items = context.Bookings
.Select(x => new { x.StartTime, EndTime = x.StartTime.AddMinutes(x.Slots * 30) })
.OrderByDescending(x => x.EndTime)
.ThenByDescending(x => x.StartTime)
.Take(10)
.ToList();
var items = context.Bookings
.GroupBy(x => new { x.StartTime.Year, x.StartTime.Month })
.Select(x => new
{
x.Key.Year,
x.Key.Month,
Count = x.Count()
})
.OrderBy(x => x.Year)
.ThenBy(x => x.Month)
.ToList();
Round(100 * Sum(Slots) / (decimal)(25 * DaysInMonth), 1)
var items = context.Bookings
.Select(booking => new
{
booking.Facility.Name,
booking.StartTime.Year,
booking.StartTime.Month,
booking.Slots,
DaysInMonth = EF.Functions.DateDiffDay(
booking.StartTime.Date.AddDays(1 - booking.StartTime.Date.Day),
booking.StartTime.Date.AddDays(1 - booking.StartTime.Date.Day).AddMonths(1)
)
})
.GroupBy(b => new { b.Name, b.Year, b.Month, b.DaysInMonth })
.Select(g => new
{
g.Key.Name,
g.Key.Year,
g.Key.Month,
Utilization = SqlDbFunctionsExtensions.SqlRound(
100 * g.Sum(b => b.Slots) / (decimal)(25 * g.Key.DaysInMonth),
1)
})
.OrderBy(r => r.Name)
.ThenBy(r => r.Year)
.ThenBy(r => r.Month)
.ToList(); namespace EFCorePgExercises.Utils
{
public static class SqlDbFunctionsExtensions
{
public static decimal SqlRound(decimal value, int precision)
=> throw new InvalidOperationException($"{nameof(SqlRound)} method cannot be called from the client side.");
private static readonly MethodInfo _sqlRoundMethodInfo = typeof(SqlDbFunctionsExtensions)
.GetRuntimeMethod(
nameof(SqlDbFunctionsExtensions.SqlRound),
new[] { typeof(decimal), typeof(int) }
);
public static void AddCustomSqlFunctions(this ModelBuilder modelBuilder)
{
modelBuilder.HasDbFunction(_sqlRoundMethodInfo)
.HasTranslation(args =>
{
return SqlFunctionExpression.Create("ROUND",
args,
_sqlRoundMethodInfo.ReturnType,
typeMapping: null);
});
}
}
} namespace EFCorePgExercises.DataLayer
{
public class ApplicationDbContext : DbContext
{
// ...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// ...
modelBuilder.AddCustomSqlFunctions();
// ...
}
}
}
مدلسازی نمونهی آن به صورت زیر است:
public class UIModel
{
public int PersianYear { set; get; }
public int[] SelectedPersianMonths { set; get; }
} var model = new UIModel
{
PersianYear = 1391,
SelectedPersianMonths = new[] { 4, 5 }
}; var itemsQuery = context.Members.AsQueryable();
// Linq chaining where clauses as an `Or` instead of `And`
var predicate = PredicateBuilder.False<Member>();
foreach (var month in model.SelectedPersianMonths)
{
var start = new DateTime(model.PersianYear, month, 1, new PersianCalendar());
var end = new DateTime(model.PersianYear, month, month <= 6 ? 31 : 30, new PersianCalendar());
// We can chain `IQueryable`s.
// itemsQuery = itemsQuery.Where(x => x.JoinDate.Date >= start && x.JoinDate.Date <= end);
// But it will be translated as an `AND`, not `OR`
predicate = predicate.Or(x => x.JoinDate.Date >= start && x.JoinDate.Date <= end);
}
itemsQuery = itemsQuery.Where(predicate);
var items = itemsQuery.Select(x => new { x.FirstName, x.Surname }).ToList(); SELECT [m].[FirstName],
[m].[Surname]
FROM [Members] AS [m]
WHERE ((CONVERT (DATE, [m].[JoinDate]) >= '2012-06-21T00:00:00')
AND (CONVERT (DATE, [m].[JoinDate]) <= '2012-07-21T00:00:00'))
OR ((CONVERT (DATE, [m].[JoinDate]) >= '2012-07-22T00:00:00')
AND (CONVERT (DATE, [m].[JoinDate]) <= '2012-08-21T00:00:00'));