Группа к неделям в LINQ к объектам

Не совсем программирование, но я терпеть не могу только макеты css только ради этого. Это контрпродуктивно, расстраивает и делает обслуживание кошмаром поплавков и наценок, когда изменение позиции одного элемента может вывести из строя всю страницу.

Это определенно не популярное мнение, но я сделал с моим расположением таблицы за 20 минут, в то время как гуру CSS тратят часы, настраивая высоту строки, поля, отступы и плавания, просто чтобы сделать что-то основное, как вертикальное центрирование абзаца.

39
задан Community 23 May 2017 в 12:18
поделиться

11 ответов

См. Также : h undo-redo , где перечислены все команды и их использование.

Есть два способа обойти дерево отмены. Один - вернуться «в прошлое». g + и g- будут проходить все узлы в дереве в хронологическом или обратном хронологическом порядке (что может немного сбивать с толку, поскольку может произвольно перемещаться между ветвями отмены, но если вы будете делать g- достаточно долго, вы всегда доберетесь туда, куда вам нужно идти). : ранее и : позже принимают дескриптор времени, например 7m или 1h ; опять же, это может произвольно перемещаться между ветвями отмены.

Другой способ - перейти к определенным узлам в дереве, используя : undo n , где n - это номер действия. (Все действия, т.е. добавления, удаления, замены текста нумеруются последовательно по мере их выполнения.) Вы можете посмотреть количество действий на листьях дерева отмены с помощью : undolist . Это позволит вам легко перепрыгивать между ветками. Затем вы можете использовать u и Ctrl-R для перемещения вверх и вниз по этой ветви.

В справке Vim есть несколько хороших примеров. Лучший способ понять, как это работает, - немного поиграть с этим.

Дайте мне знать, если вам повезет.

Обновление

Вот еще одно предложение, которое может позволить вам использовать LINQ to Entities для всего этого.

(t.TargetDate.Days - firstDay.Days) / 7

Это просто расширяет операцию так, чтобы только Выполняется целочисленное вычитание, а не вычитание DateTime .

В настоящее время он не протестирован, поэтому может работать, а может и не работать ...

40
ответ дан 27 November 2019 в 02:44
поделиться

Ну, может потребоваться больше работы в зависимости от того, как индексируется БД, но вы можете просто отсортировать по дням, а затем выполнить сопоставление день -> неделя на стороне клиента.

-2
ответ дан 27 November 2019 в 02:44
поделиться

Вы можете попробовать метод расширения для выполнения преобразования:

static int WeekNumber( this DateTime dateTime, DateTime firstDay) {
    return (dateTime - firstDay).Days / 7;
}

Тогда у вас будет:

DateTime firstDay = GetFirstDayOfFirstWeekOfYear();
var userTimes = from t in context.TrackedTimes
                group t by new {t.User.UserName, t.TargetDate.WeekNumber( firstDay)} into ut
                select new
                {
                    UserName = ut.Key.UserName,
                    WeekNumber = ut.Key.WeekNumber,
                    Minutes = ut.Sum(t => t.Minutes)
                };
-2
ответ дан 27 November 2019 в 02:44
поделиться

Здесь - это список методов, поддерживаемых LINQ to Entities.

Единственный вариант, который я вижу, - это получить номер недели из DateTime.Month и DateTime.Day. Примерно так:

int yearToQueryIn = ...;
int firstWeekAdjustment = (int)GetDayOfWeekOfFirstDayOfFirstWeekOfYear(yearToQueryIn);

from t in ...
where t.TargetDate.Year == yearToQueryIn
let month = t.TargetDate.Month
let precedingMonthsLength =
    month == 1 ? 0 :
    month == 2 ? 31 :
    month == 3 ? 31+28 :
    month == 4 ? 31+28+31 : 
    ...
let dayOfYear = precedingMonthsLength + t.TargetDate.Day
let week = (dayOfYear + firstWeekAdjustment) / 7
group by ... 
2
ответ дан 27 November 2019 в 02:44
поделиться

Я не использую Linq to Entities, но если он поддерживает .Year,. (Это может потребоваться изменить в зависимости от того, в какой день начинается ваша неделя.)

Proviso. Это формула, которую я никогда не использовал «по-настоящему». Я ввел вручную (не помню, но, возможно, скопировал это из книги), что означает, что, хотя я утроил проверку, у меня были правильные скобки, возможно, источник был неправильным. Итак, вам необходимо убедиться, что он работает перед использованием.

Лично я бы предпочел возвращать семикратный объем данных и фильтровать локально, а не использовать что-то подобное (что, возможно, объясняет, почему я никогда не пользовался форумла)

2
ответ дан 27 November 2019 в 02:44
поделиться

У меня была именно эта проблема в моем приложении для учета рабочего времени, которое должно сообщать о задачах по неделям. Я пробовал использовать арифметический подход, но ничего разумного не получилось. В итоге я просто добавил в базу данных новый столбец с номером недели и вычислил его для каждой новой строки. Внезапно вся боль прошла. Я ненавидел это делать, поскольку я очень верю в DRY , но мне нужно было добиться прогресса. Не тот ответ, который вам нужен, а точка зрения другого пользователя. Я буду смотреть это, чтобы получить достойный ответ.

6
ответ дан 27 November 2019 в 02:44
поделиться

Хорошо, это возможно, но это огромный PITA, и он обходит LINQ - часть Entity Framework. Потребовалось некоторое исследование, но вы можете выполнить то, что хотите, с помощью специфической для поставщика функции SqlServer SqlServer.DateDiff () и "Entity SQL". Это означает, что вы вернулись к строковым запросам и вручную заполняете настраиваемые объекты, но он делает то, что вы хотите. Возможно, вам удастся немного уточнить это, используя Select вместо цикла foreach и тому подобное, но я действительно заставил это работать с созданным дизайнером набором сущностей YourEntities.

void getTimes()
{
    YourEntities context = new YourEntities();
    DateTime firstDay = GetFirstDayOfFirstWeekOfYear();
    var weeks = context.CreateQuery<System.Data.Common.DbDataRecord>(
        "SELECT t.User.UserName, SqlServer.DateDiff('DAY', @beginDate, t.TargetDate)/7 AS WeekNumber " +
        "FROM YourEntities.TrackedTimes AS t " +
        "GROUP BY SqlServer.DateDiff('DAY', @beginDate, t.TargetDate)/7, t.User.UserName", new System.Data.Objects.ObjectParameter("beginDate", firstDay));
    List<customTimes> times = new List<customTimes>();
    foreach (System.Data.Common.DbDataRecord rec in weeks)
    {
        customTimes time = new customTimes()
        {
            UserName = rec.GetString(0),
            WeekNumber = rec.GetInt32(1)
        };
        times.Add(time);
    }
}

class customTimes
{
    public string UserName{ get; set; }
    public int WeekNumber { get; set; }
}
2
ответ дан 27 November 2019 в 02:44
поделиться

учитывается ли лямбда? Я начал с синтаксиса linq, но, кажется, думаю о лямбда-выражениях C # 3.0, когда дело доходит до декларативного программирования.

public static void TEST()
{
    // creating list of some random dates
    Random rnd = new Random();
    List<DateTime> lstDte = new List<DateTime>();
    while (lstDte.Count < 100)
    {
        lstDte.Add(DateTime.Now.AddDays((int)(Math.Round((rnd.NextDouble() - 0.5) * 100))));
    }
    // grouping 
    var weeksgrouped = lstDte.GroupBy(x => (DateTime.MaxValue - x).Days / 7);
}
-1
ответ дан 27 November 2019 в 02:44
поделиться

Странно, что никто еще не опубликовал метод GetWeekOfYear платформы .NET Framework.

просто сделайте свой первый выбор, добавьте фиктивное свойство weeknumber, затем переберите их все и используйте этот метод для установите правильный номер недели для вашего типа, он должен быть достаточно быстрым, чтобы выполнить один цикл между двумя выборками, не так ли?:

public static int GetISOWeek(DateTime day)
{
  return System.Globalization.CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(day, System.Globalization.CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
2
ответ дан 27 November 2019 в 02:44
поделиться

Я думаю, что единственная проблема, с которой вы столкнулись, - это арифметические операции с типом DateTime, попробуйте следующий пример. Он сохраняет операцию в БД как скалярную функцию, возвращает только желаемые сгруппированные результаты. Функция .Days не будет работать с вашей стороны, потому что реализация TimeSpan ограничена и (в основном) доступна только в SQL 2008 и .Net 3.5 SP1, дополнительные примечания здесь по этому .

var userTimes = from t in context.TrackedTimes
    group t by new 
    {
        t.User.UserName, 
        WeekNumber = context.WeekOfYear(t.TargetDate)
    } into ut
    select new 
    {
        UserName = ut.Key.UserName,
        WeekNumber = ut.Key.WeekNumber,
        Minutes = ut.Sum(t => t.Minutes)
    };

Функция в базе данных добавлено в ваш контекст (как context.WeekOfYear):

CREATE FUNCTION WeekOfYear(@Date DateTime) RETURNS Int AS 
BEGIN
RETURN (CAST(DATEPART(wk, @Date) AS INT))
END

Для дополнительной информации: Вот поддерживаемые методы DateTime, которые правильно транслируются в сценарии LINQ to SQL

1
ответ дан 27 November 2019 в 02:44
поделиться

Вы можете попробовать сгруппироваться по годам и неделямNumber, получив его в собственность DayOfYear

var userTimes = from t in context.TrackedTimes
                group t by new {t.User.UserName, Year =  t.TargetDate.Year, WeekNumber = t.TargetDate.DayOfYear/7} into ut
                select new
                {
                    UserName = ut.Key.UserName,
                    WeekNumber = ut.Key.WeekNumber,
                    Minutes = ut.Sum(t => t.Minutes)
                };
-1
ответ дан 27 November 2019 в 02:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: