Руководство по подходу к созданию отчетов для Razor Page Report

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

TripId
ClientName
PickUpDateTime
PickUpLocation
PickUpDriver
PickUpVehicle

ApptDateTime
ApptLocation

ReturnDateTime
ReturnLocation
ReturnDriver
ReturnVehicle

Пользователю хотелось бы, чтобы расписание водителя содержало всю информацию «от» в одном столбце и всю информацию «до» в другом столбце.

По сути, это означает, что они хотели бы, чтобы информация о Самовывозе и информация о Приложении были в одном столбце (поскольку вы приходите «из» Пикапа, а затем, когда вы закончите работу с Приложением, вы будете приходить «из» Приложения). то же самое касается информации «кому». Вы идете «в» приложение, а затем идете «в» обратное место.

Поскольку вся поездка хранится в одной строке базы данных Trip, как мне это сделать?

Я попытался создать 3 Iqueryables для временных таблиц и назвать все поля в двух Iqueryables одинаковыми, но затем, когда я присоединяюсь к ним с помощью третьего Iqueryable, я не знаю, как заставить запрос просматривать оба «FromDateTime», например . Вот что я имею в виду:

Запросы:

        IQueryable<ReportModelPU> scheduledTripsPU = from x in _context.Trip
                                                 join y in _context.Client on x.ClientName equals y.DisplayName
                                                 select new ReportModelPU
                                                {
                                                    ClientName = y.DisplayName,
                                                    Driver = x.PickUpDriver,
                                                    Vehicle = x.PickUpVehicle,
                                                    FromDateTime = x.PickUpDateTime,
                                                    FromLocation = x.PickUpLocation,
                                                    ToDateTime = x.ApptDateTime,
                                                    ToLocation = x.ApptLocation,...

        IQueryable<ReportModelRT> scheduledTripsRT = from x in _context.Trip
                                                 join y in _context.Client on x.ClientName equals y.DisplayName
                                                 select new ReportModelRT
                                                {
                                                    ClientName = y.DisplayName,
                                                    Driver = x.ReturnDriver,
                                                    Vehicle = x.ReturnVehicle,
                                                    FromDateTime = x.ReturnDateTime,
                                                    FromLocation = x.ApptLocation,
                                                    ToLocation = x.ReturnLocation,...

        IQueryable<ReportModel> scheduledTripsALL = from x in scheduledTripsPU
                                                    where (x.FromDateTime >= v && x.FromDateTime <= to && x.Driver == selDriver) || (x.FromDateTime >= v && x.FromDateTime <= to && x.Driver == selDriver)
                                                    join y in scheduledTripsRT on x.ClientName equals y.ClientName
                                                    where (y.FromDateTime >= v && y.FromDateTime <= to && y.Driver == selDriver) || (y.FromDateTime >= v && y.FromDateTime <= to && y.Driver == selDriver)
                                                    select new ReportModel
                                                   {
                                                          ClientName = x.ClientName,
                                                          FromDateTime = x.FromDateTime || y.FromDateTime,
                                                          FromLocation = x.FromLocation || y.FromLocation,...

Надеюсь, это имеет смысл. Пользователь хотел бы, чтобы полученный отчет располагался в хронологическом порядке, чтобы водитель мог просто прочитать страницу и узнать следующий этап путешествия. ПРИМЕЧАНИЕ. Драйвер погрузки и возврата могут быть разными для одного клиента. Итак, водитель Джон Доу может забрать Эми в 8:30 утра и высадить ее в 9 утра, затем поехать за Нелли, чтобы высадить ее где-нибудь еще, и т. д. Все эти моменты должны быть упорядочены по ВРЕМЕНИ, а не по ВРЕМЕНИ. клиент.

Любые идеи будут приветствоваться. Можно ли объединить эти запросы? Я не продвинутый программист и мне удается разобраться с простыми вещами. Спасибо!

ОБНОВЛЕНИЕ: добился некоторого прогресса и фактически получил рабочий запрос. Изменено и просто .

Затем я отредактировал IQueryable ScheduledTripsALL, чтобы он был объединением первых двух запросов:

Queryable<ReportModel> scheduledTripsALL = scheduledTripsPU.Concat(scheduledTripsRT);

Моя единственная проблема сейчас заключается в том, что, хотя отчет будет работать, если исходная таблица Trip будет отредактирована, отчет не будет возвращать никаких значений. Думаете, что мне следует сделать какой-то сброс или обновление? Если вы знаете, пожалуйста, скажите мне. Борьба с этой частью.

ОТРЕДАКТИРОВАНО, ЧТОБЫ ДОБАВИТЬ: Индекс.cshtml:

@page
@model Transport.Pages.Reports.DriverSchedule.IndexModel

@{
    ViewData["Title"] = "Daily Driver Schedule";
}

<h1>Daily Driver Schedule</h1>
    
<form asp-page = "./Index" method = "get">
    <div class = "form-actions no-color">
        <p>
            <h5>Report Date Range</h5>
            <div class = "col-25">
                <table class = "table table-borderless" style = "width:100%">
                    <tr width = "100%">
                        <td width = "33%" style = "text-align: left">
                            Input Report Date: <input asp-for = "ReportDate" />
                        </td>
                        <td align = "left" width = "34%" style = "text-align: left">
                        <select asp-for = "ScheduledTripsALL" name = "selDriver" id = "selDriver" class = "form-select" asp-items = "@(new SelectList(Model.DisplayDriverData.OrderBy(x => x.DisplayName),"DisplayName", "DisplayName"))"><option value = "" selected disabled>---Select Driver---</option></select>
                        </td>
                    </tr>
                </table>
            <input type = "submit" value = "Filter Report" class = "btn btn-primary mx-2" />
            <a asp-page = "./Index" class = "btn btn-link mx-2">Clear Dates</a>
            </div>
        </p>
    </div>
</form>
<div id = "PrintThis" style = "width:contain; overflow-x:auto">
    <div class = "col-25">
        <h2 class = "text-primary" align = "center">Ontario County Transportation Scheduling</h2>
        <h5 class = "text-primary" align = "center">Daily Driver Schedule</h5>
        <h5 class = "text-primary" align = "center">@ViewData["startparameter"]</h5>
        <h5 class = "text-primary" align = "center">@ViewData["driverparameter"]</h5>
    </div>
    <br />
    <table class = "table table-bordered" style = "width:100%">
        <thead>
            <tr>
                <th style = "text-align: left" width = "25%">
                    Client Data
                </th>
                <th style = "text-align: left" width = "25%">
                    From Data
                </th>
                <th style = "text-align: left" width = "25%">
                    To Data
                </th>
            </tr>
        </thead>
        <tbody>
            @foreach(var item in Model.ScheduledTripsALL.OrderBy(i =>i.FromDateTime))
            {
            <tr width = "100%">
                <td width = "25%" style = "text-align: left">
                    <b>@Html.DisplayNameFor(modelItem => item.ClientName):</b>   @Html.DisplayFor(modelItem => item.ClientName) <br/>
                </td>
                <td width = "25%" style = "text-align: left">
                    <b>Time:</b> <b><font color = "red">@Convert.ToString(string.Format("{0:hh:mm tt}", item.FromDateTime))</font></b><br />
                    <b>Address:</b><br />
                    @Html.DisplayFor(modelItem => item.FromLocation)@Html.DisplayFor(modelItem => item.FromNonSiteLocation)<br />
                    @Html.DisplayFor(modelItem => item.FromAddr1)<br /> 
                    @Html.DisplayFor(modelItem => item.FromAddr2)<br />
                    @Html.DisplayFor(modelItem => item.FromCity)<br />
                </td>
                <td width = "25%" style = "text-align: left">
                        <b>Time:</b> <b>
                            <font color = "red">
                                @if (item.ToDateTime == item.FromDateTime)
                                {
                                    
                                }
                                else
                                {
                                    @Convert.ToString(string.Format("{0:hh:mm tt}", item.ToDateTime))
                                }
                            </font></b><br />
                        <b>Address:</b><br />
                    @Html.DisplayFor(modelItem => item.ToLocation)@Html.DisplayFor(modelItem => item.ToNonSiteLocation)<br />
                    @Html.DisplayFor(modelItem => item.ToAddr1)<br /> 
                    @Html.DisplayFor(modelItem => item.ToAddr2)<br />
                    @Html.DisplayFor(modelItem => item.ToCity)<br />
                </td>
            </tr>
            }
        </tbody>
    </table>
</div>

<button type = "submit" onclick = "printDiv('PrintThis')" class = "btn btn-primary" style = "width:300px;">Print (Select Landscape)</button>
<br />
<br />

<div>
    @{
        var prevDisabled = !Model.ScheduledTripsALL.HasPreviousPage ? "disabled" : "";
        var nextDisabled = !Model.ScheduledTripsALL.HasNextPage ? "disabled" : "";
    }

    <a asp-page = "./Index"
       asp-route-pageIndex = "@(Model.ScheduledTripsALL.PageIndex - 1)"
       asp-route-reportDate = "@Model.ReportDate"
       class = "btn btn-primary @prevDisabled">
        Previous
    </a>
    <br />
    <br />
    <a asp-page = "./Index"
       asp-route-pageIndex = "@(Model.ScheduledTripsALL.PageIndex + 1)"
       asp-route-reportDate = "@Model.ReportDate"
       class = "btn btn-primary @nextDisabled">
        Next
    </a>

</div>

@section Scripts
{
    <script language = "javascript">
        function printDiv(divName) {
            var printContents = document.getElementById(divName).innerHTML;
            var originalContents = document.body.innerHTML;

            document.body.innerHTML = printContents;

            window.print();

            document.body.innerHTML = originalContents;
        }

    </script>

И Index.cs:

using Transport.Data;
using Transport.Model;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;

namespace Transport.Pages.Reports.DriverSchedule;

public class IndexModel : PageModel
{
    private readonly ApplicationDbContext _db;

    public IndexModel(ApplicationDbContext db)
    {
        _db = db;
    }

    public Trip Trip { get; set; }
    public Client Client { get; set; }
    public Driver Driver { get; set; }
    [BindProperty(SupportsGet = true), DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime ReportDate { get; set; }
    public string? DriverName { get; set; }
    public string? DriverPhone { get; set; }
    public IEnumerable<Driver> DisplayDriverData { get; set; }

    public PaginatedList<ReportModel> ScheduledTripsPU { get; set; } = default!;
    public PaginatedList<ReportModel> ScheduledTripsRT { get; set; } = default!;
    public PaginatedList<ReportModel> ScheduledTripsALL { get; set; } = default!;

    public async Task OnGet(string? selDriver, int? pageIndex)
    {
        var from = ReportDate;
        var v = from;
        var s = from.ToShortDateString();
        var to = ReportDate.AddDays(1);
        DriverName = selDriver;
        await _db.Driver.Select(a => a.DriverId).ToListAsync();
        DisplayDriverData = await _db.Driver.ToListAsync();


        IQueryable<ReportModel> scheduledTripsPU = (IQueryable<ReportModel>)(from x in _db.Trip
                                                 join y in _db.Client on x.ClientName equals y.DisplayName
                                                 where (x.PickUpDateTime >= v && x.PickUpDateTime <= to && x.PickUpDriver == selDriver) || (x.PickUpDateTime >= v && x.PickUpDateTime <= to && x.PickUpDriver == selDriver)
                                                 orderby x.PickUpDateTime
                                                 select new ReportModel
                                                {
                                                    ClientName = y.DisplayName,
                                                    ClientSex = y.Gender,
                                                    ClientAge = y.Age,
                                                    ClientAgeCategory = y.Category,
                                                    ClientCarSeat = y.CarSeat,
                                                    ClientWeight = y.Weight,
                                                    ClientCaseWorker = y.CaseWorkerName,
                                                    ClientCaseWorkerPhone = y.CaseWorkerPhone,

                                                    Driver = x.PickUpDriver,
                                                    VehiclePhone = x.PickUpVehiclePhone,
                                                    Vehicle = x.PickUpVehicle,
                                                    
                                                    FromDateTime = x.PickUpDateTime,
                                                    FromLocation = x.PickUpLocation,
                                                    FromNonSiteLocation = x.NonSitePickUpLocation,
                                                    FromAddr1 = x.PickUpAddr1,
                                                    FromAddr2 = x.PickUpAddr2,
                                                    FromCity = x.PickUpCity,
                                                    FromDirections = x.PickUpDirections,
                                                    FromPhone = x.PickUpPhone,

                                                    ToDateTime = x.ApptDateTime,
                                                    ToLocation = x.ApptLocation,
                                                    ToNonSiteLocation = x.NonSiteApptLocation,
                                                    ToAddr1 = x.ApptAddr1,
                                                    ToAddr2 = x.ApptAddr2,
                                                    ToCity = x.ApptCity,
                                                    ToDirections = x.ApptDirections,
                                                    ToPhone = x.ApptPhone,
                                                }); ;

        IQueryable<ReportModel> scheduledTripsRT = (IQueryable<ReportModel>)(from x in _db.Trip
                                                 join y in _db.Client on x.ClientName equals y.DisplayName
                                                 where (x.ReturnDateTime >= v && x.ReturnDateTime <= to) || (x.ReturnDateTime >= v && x.ReturnDateTime <= to)
                                                 orderby x.ReturnDateTime
                                                 select new ReportModel
                                                 {
                                                     ClientName = y.DisplayName,
                                                     ClientSex = y.Gender,
                                                     ClientAge = y.Age,
                                                     ClientAgeCategory = y.Category,
                                                     ClientCarSeat = y.CarSeat,
                                                     ClientWeight = y.Weight,
                                                     ClientCaseWorker = y.CaseWorkerName,
                                                     ClientCaseWorkerPhone = y.CaseWorkerPhone,

                                                     Driver = x.ReturnDriver,
                                                     VehiclePhone = x.ReturnVehiclePhone,
                                                     Vehicle = x.ReturnVehicle,

                                                     FromDateTime = x.ReturnDateTime,
                                                     FromLocation = x.ApptLocation,
                                                     FromNonSiteLocation = x.ApptLocation,
                                                     FromAddr1 = x.ApptAddr1,
                                                     FromAddr2 = x.ApptAddr2,
                                                     FromCity = x.ApptCity,
                                                     FromDirections = x.ApptDirections,
                                                     FromPhone = x.ApptPhone,

                                                     ToDateTime = x.ReturnDateTime,
                                                     ToLocation = x.ReturnLocation,
                                                     ToNonSiteLocation = x.NonSiteReturnLocation,
                                                     ToAddr1 = x.ReturnAddr1,
                                                     ToAddr2 = x.ReturnAddr2,
                                                     ToCity = x.ReturnCity,
                                                     ToDirections = x.ReturnDirections,
                                                     ToPhone = x.ReturnPhone,
                                                 }); ;

        IQueryable<ReportModel> scheduledTripsALL = scheduledTripsPU.Concat(scheduledTripsRT);

        int casesPerPage = 20;
        ScheduledTripsALL = await PaginatedList<ReportModel>.CreateAsync(
            scheduledTripsALL, pageIndex ?? 1, casesPerPage);

        ViewData["startparameter"] = $"Selected Report Date: {s}";
        ViewData["driverparameter"] = $"Driver: {selDriver}";

    }

}

Я сократил содержимое страницы просто для легкости, поэтому в запросах .cs больше полей.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваше решение не поддерживает живое соединение с исходными источниками данных. Это означает, что если базовые данные в таблице Trip изменятся, эти изменения не отразятся автоматически в вашем отчете. Чтобы гарантировать, что ваш отчет отражает все изменения, внесенные в таблицу Trip, вам необходимо повторно запрашивать данные каждый раз, когда вы создаете отчет.

или если вы хотите динамически обновлять отчет при обновлении таблицы, для этого вы можете:

  1. Периодическое обновление отчета: (событие опроса) Для этого вы можете создать функцию, которая вызывается через небольшие промежутки времени и повторно генерирует отчет или обновляет часть отчета: (пример кода)
using System;
using System.Linq;
using System.Threading;

class Program
{
    static IQueryable<ReportModel> scheduledTripsALL; // Define this variable at a broader scope

    static void Main()
    {
        scheduledTripsALL = RefreshReport(null); // Initialize scheduledTripsALL
        Timer timer = new Timer(RefreshReport, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
        Thread.Sleep(Timeout.Infinite);
    }

    static void RefreshReport(object state)
    {
        scheduledTripsALL = scheduledTripsPU.Concat(scheduledTripsRT);
    }
}
  1. Обновить отчет об обновлении таблицы поездок: Для этого вы можете создать триггер и функцию базы данных, которые будут уведомлять об обновлении таблицы, и вы можете фиксировать это событие и соответствующим образом обновлять свой отчет:
CREATE OR REPLACE FUNCTION notify_trip_change()
RETURNS trigger AS
$BODY$
BEGIN
    PERFORM pg_notify('trip_change', '');
    RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;

CREATE TRIGGER trip_trigger
AFTER INSERT OR UPDATE OR DELETE
ON Trip
FOR EACH ROW
EXECUTE FUNCTION notify_trip_change();

using System;
using Npgsql;

class Program
{
    static void Main()
    {
        var connString = "Host=myhost;Username=myuser;Password=mypass;Database=mydb";
        using var conn = new NpgsqlConnection(connString);
        conn.Open();

        conn.Notification += (sender, args) =>
        {
            if (args.Payload == "trip_change")
            {
                 RefreshReport();
            }
        };

        using var cmd = new NpgsqlCommand("LISTEN trip_change", conn);
        cmd.ExecuteNonQuery();
    }

    static void RefreshReport(object state)
    {
        scheduledTripsALL = scheduledTripsPU.Concat(scheduledTripsRT);
    }
}

Надеюсь, это то, что вы ищете.

РЕДАКТИРОВАТЬ Вы можете создать новую функцию для периодического обновления отчета, скажем, каждые 5 минут:

    public async Task<IActionResult> OnGetRefreshDataAsync(string? selDriver)
{
    var from = ReportDate;
    var to = ReportDate.AddDays(1);
    IQueryable<ReportModel> scheduledTripsPU = (IQueryable<ReportModel>)(
        from x in _db.Trip
        join y in _db.Client on x.ClientName equals y.DisplayName
        where (x.PickUpDateTime >= v && x.PickUpDateTime <= to && x.PickUpDriver == selDriver) || (x.PickUpDateTime >= v && x.PickUpDateTime <= to && x.PickUpDriver == selDriver)orderby x.PickUpDateTime
        select new ReportModel
        {
            ClientName = y.DisplayName,
            ClientSex = y.Gender,
            ClientAge = y.Age,
            ClientAgeCategory = y.Category,
            ClientCarSeat = y.CarSeat,
            ClientWeight = y.Weight,
            ClientCaseWorker = y.CaseWorkerName,
            ClientCaseWorkerPhone = y.CaseWorkerPhone,
            Driver = x.PickUpDriver,
            VehiclePhone = x.PickUpVehiclePhone,
            Vehicle = x.PickUpVehicle,
            FromDateTime = x.PickUpDateTime,
            FromLocation = x.PickUpLocation,
            FromNonSiteLocation = x.NonSitePickUpLocation,
            FromAddr1 = x.PickUpAddr1,
            FromAddr2 = x.PickUpAddr2,
            FromCity = x.PickUpCity,
            FromDirections = x.PickUpDirections,
            FromPhone = x.PickUpPhone,
            ToDateTime = x.ApptDateTime,
            ToLocation = x.ApptLocation,
            ToNonSiteLocation = x.NonSiteApptLocation,
            ToAddr1 = x.ApptAddr1,
            ToAddr2 = x.ApptAddr2,
            ToCity = x.ApptCity,
            ToDirections = x.ApptDirections,
            ToPhone = x.ApptPhone,
        }

    );
    IQueryable<ReportModel> scheduledTripsRT = (IQueryable<ReportModel>)(
        from x in _db.Trip
        join y in _db.Client on x.ClientName equals y.DisplayName
        where (x.ReturnDateTime >= v && x.ReturnDateTime <= to) || (x.ReturnDateTime >= v && x.ReturnDateTime <= to)orderby x.ReturnDateTime
        select new ReportModel
        {
            ClientName = y.DisplayName,
            ClientSex = y.Gender,
            ClientAge = y.Age,
            ClientAgeCategory = y.Category,
            ClientCarSeat = y.CarSeat,
            ClientWeight = y.Weight,
            ClientCaseWorker = y.CaseWorkerName,
            ClientCaseWorkerPhone = y.CaseWorkerPhone,
            Driver = x.ReturnDriver,
            VehiclePhone = x.ReturnVehiclePhone,
            Vehicle = x.ReturnVehicle,
            FromDateTime = x.ReturnDateTime,
            FromLocation = x.ApptLocation,
            FromNonSiteLocation = x.ApptLocation,
            FromAddr1 = x.ApptAddr1,
            FromAddr2 = x.ApptAddr2,
            FromCity = x.ApptCity,
            FromDirections = x.ApptDirections,
            FromPhone = x.ApptPhone,
            ToDateTime = x.ReturnDateTime,
            ToLocation = x.ReturnLocation,
            ToNonSiteLocation = x.NonSiteReturnLocation,
            ToAddr1 = x.ReturnAddr1,
            ToAddr2 = x.ReturnAddr2,
            ToCity = x.ReturnCity,
            ToDirections = x.ReturnDirections,
            ToPhone = x.ReturnPhone,
        }

    );
    ;
    var scheduledTripsALL = await scheduledTripsPU.Concat(scheduledTripsRT).ToListAsync();
    ViewData["startparameter"] = $"Selected Report Date: {s}";
    ViewData["driverparameter"] = $"Driver: {selDriver}";
    return new JsonResult(scheduledTripsALL);
} 

и для вызова этой функции добавьте код в раздел сценариев на своей странице:

<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
        function fetchData() {
            var selDriver = $('#selDriver').val();
            $.ajax({
                url: '@Url.Page("./Index", "RefreshData")',
                data: { selDriver: selDriver },
                success: function(data) {
                    updateUI(data);
                },
                error: function(err) {
                    console.error("Error fetching data:", err);
                }
            });
        }

        function updateUI(data) {
            var tableBody = $('#PrintThis tbody');
            tableBody.empty();

            data.forEach(function(item) {
                var fromDateTime = new Date(item.FromDateTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
                var toDateTime = new Date(item.ToDateTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

                var row = `
                    <tr width = "100%">
                        <td width = "25%" style = "text-align: left">
                            <b>Client Name:</b> ${item.ClientName} <br/>
                        </td>
                        <td width = "25%" style = "text-align: left">
                            <b>Time:</b> <b><font color = "red">${fromDateTime}</font></b><br />
                            <b>Address:</b><br />
                            ${item.FromLocation}${item.FromNonSiteLocation}<br />
                            ${item.FromAddr1}<br /> 
                            ${item.FromAddr2}<br />
                            ${item.FromCity}<br />
                        </td>
                        <td width = "25%" style = "text-align: left">
                            <b>Time:</b> <b><font color = "                                red">${toDateTime}</font></b><br />
                            <b>Address:</b><br />
                            ${item.ToLocation}${item.ToNonSiteLocation}<br />
                            ${item.ToAddr1}<br /> 
                            ${item.ToAddr2}<br />
                            ${item.ToCity}<br />
                        </td>
                    </tr>`;
                tableBody.append(row);
            });
        }

        setInterval(fetchData, 5 * 60 * 1000);

        $(document).ready(function() {
            fetchData();
        });

        function printDiv(divName) {
            var printContents = document.getElementById(divName).innerHTML;
            var originalContents = document.body.innerHTML;

            document.body.innerHTML = printContents;

            window.print();

            document.body.innerHTML = originalContents;
        }
    </script>

РЕДАКТИРОВАТЬ Чтобы продолжить обновление отчета о подходе к обновлению таблицы отключений:

  1. Создайте триггер и функцию PostgreSQL в среде вашей базы данных с помощью запросов, упомянутых выше.

  2. Установите пакет SignalR:

    dotnet добавить пакет Microsoft.AspNetCore.SignalR

  3. Создайте хаб для управления общением с клиентами:

    использование Microsoft.AspNetCore.SignalR; использование System.Threading.Tasks;

    общедоступный класс TripChangeHub: Hub { общедоступная асинхронная задача NotifyTripChange() { await Clients.All.SendAsync("TripChanged"); } }

  4. Настройте SignalR в Startup.cs:

    публичный класс стартапа { общественная недействительность ConfigurationServices (службы IServiceCollection) { услуги.AddSignalR(); услуги.AddSingleton(); }

     public void Configure(IApplicationBuilder app, IHostingEnvironment env)
     {
         app.UseSignalR(routes =>
         {
             routes.MapHub<TripChangeHub>("/tripChangeHub");
         });
     }
    

    }

  5. Измените фоновую службу для использования SignalR: внедрите IHubContext в службу TripChangeListener и используйте ее для уведомления клиентов при обнаружении изменений.

    использование Microsoft.Extensions.Hosting; использование Microsoft.Extensions.Logging; использование Microsoft.AspNetCore.SignalR; использование Npgsql; использование системы; использование System.Threading; использование System.Threading.Tasks; использование Транспорт.Данные; использование Microsoft.EntityFrameworkCore; используя System.Linq;

    общедоступный класс TripChangeListener: BackgroundService { частный только для чтения ApplicationDbContext _db; частный ILogger только для чтения _logger; частный IHubContext только для чтения _hubContext; частная строка только для чтения _connectionString;

     public TripChangeListener(ApplicationDbContext db, ILogger<TripChangeListener> logger, IHubContext<TripChangeHub> hubContext, string connectionString)
     {
         _db = db;
         _logger = logger;
         _hubContext = hubContext;
         _connectionString = connectionString;
     }
    
     protected override async Task ExecuteAsync(CancellationToken stoppingToken)
     {
         await Task.Yield(); // To avoid blocking the calling thread
    
         try
         {
             await using var conn = new NpgsqlConnection(_connectionString);
             await conn.OpenAsync(stoppingToken);
    
             conn.Notification += async (o, e) => {
                 if (e.Condition == "trip_change")
                 {
                     _logger.LogInformation("Trip change detected. Refreshing report.");
                     await RefreshReportAsync();
                     await _hubContext.Clients.All.SendAsync("TripChanged");
                 }
             };
    
             await using var listenCmd = new NpgsqlCommand("LISTEN trip_change;", conn);
             await listenCmd.ExecuteNonQueryAsync(stoppingToken);
    
             _logger.LogInformation("Listening for trip changes.");
    
             while (!stoppingToken.IsCancellationRequested)
             {
                 await conn.WaitAsync(stoppingToken); // This will block until a notification is received
             }
         }
         catch (Exception ex)
         {
             _logger.LogError(ex, "An error occurred while listening for trip changes.");
         }
     }
    
     private async Task RefreshReportAsync()
     {
         var reportDate = DateTime.Today;
         var from = reportDate;
         var to = reportDate.AddDays(1);
    

    IQueryable ScheduledTripsPU = (IQueryable)( из x в _db.Trip присоединиться к y в _db.Client на x.ClientName равно y.DisplayName где (x.PickUpDateTime >= v && x.PickUpDateTime <= to && x.PickUpDriver == selDriver) || (x.PickUpDateTime >= v && x.PickUpDateTime <= to && x.PickUpDriver == selDriver)orderby x.PickUpDateTime выберите новую модель отчета { ИмяКлиента = y.DisplayName, ClientSex = y.Gender, ClientAge = y.Age, ClientAgeCategory = y.Category, ClientCarSeat = y.CarSeat, ClientWeight = y.Weight, ClientCaseWorker = y.CaseWorkerName, ClientCaseWorkerPhone = y.CaseWorkerPhone, Драйвер = x.PickUpDriver, VehiclePhone = x.PickUpVehiclePhone, Транспортное средство = x.PickUpVehicle, FromDateTime = x.PickUpDateTime, FromLocation = x.PickUpLocation, FromNonSiteLocation = x.NonSitePickUpLocation, FromAddr1 = x.PickUpAddr1, FromAddr2 = x.PickUpAddr2, FromCity = x.PickUpCity, FromDirections = x.PickUpDirections, FromPhone = x.PickUpPhone, ToDateTime = x.ApptDateTime, ToLocation = x.ApptLocation, ToNonSiteLocation = x.NonSiteApptLocation, ToAddr1 = x.ApptAddr1, ToAddr2 = x.ApptAddr2, ToCity = x.ApptCity, ToDirections = x.ApptDirections, ToPhone = x.ApptPhone, }

         );
         IQueryable<ReportModel> scheduledTripsRT = (IQueryable<ReportModel>)(
             from x in _db.Trip
             join y in _db.Client on x.ClientName equals y.DisplayName
             where (x.ReturnDateTime >= v && x.ReturnDateTime <= to) || (x.ReturnDateTime >= v && x.ReturnDateTime <= to)orderby x.ReturnDateTime
             select new ReportModel
             {
                 ClientName = y.DisplayName,
                 ClientSex = y.Gender,
                 ClientAge = y.Age,
                 ClientAgeCategory = y.Category,
                 ClientCarSeat = y.CarSeat,
                 ClientWeight = y.Weight,
                 ClientCaseWorker = y.CaseWorkerName,
                 ClientCaseWorkerPhone = y.CaseWorkerPhone,
                 Driver = x.ReturnDriver,
                 VehiclePhone = x.ReturnVehiclePhone,
                 Vehicle = x.ReturnVehicle,
                 FromDateTime = x.ReturnDateTime,
                 FromLocation = x.ApptLocation,
                 FromNonSiteLocation = x.ApptLocation,
                 FromAddr1 = x.ApptAddr1,
                 FromAddr2 = x.ApptAddr2,
                 FromCity = x.ApptCity,
                 FromDirections = x.ApptDirections,
                 FromPhone = x.ApptPhone,
                 ToDateTime = x.ReturnDateTime,
                 ToLocation = x.ReturnLocation,
                 ToNonSiteLocation = x.NonSiteReturnLocation,
                 ToAddr1 = x.ReturnAddr1,
                 ToAddr2 = x.ReturnAddr2,
                 ToCity = x.ReturnCity,
                 ToDirections = x.ReturnDirections,
                 ToPhone = x.ReturnPhone,
             }
    
         );
    
         var scheduledTripsALL = scheduledTripsPU.Concat(scheduledTripsRT).ToList();
    
         // You might need to store it in a shared location or signal a refresh to the UI
     }
    

    }

  6. Настройте интерфейс для прослушивания уведомлений.

Надеюсь это поможет

Да, это то, что я ищу. Всего несколько вопросов. Я не совсем уверен, где мне разместить этот код? Проводится ли периодический опрос на самом Report.cs? Куда пойдет триггерный код отключения, если я захочу это сделать? У меня есть индекс поездки, создание, редактирование и удаление файлов .cs. Или это просто в отдельном файле класса? Я думаю, что, поскольку таблица Trip обновляется несколько раз в день, я хочу обновлять отчет каждый раз, когда происходит обновление. Процедура пользователя заключается в вводе данных и последующей печати отчета, поэтому, если он не обновился вовремя, это проблема.

MelB 12.06.2024 16:32

Как вы визуализируете свой отчет, можете ли вы поделиться этим кодом/классом?

hassaan mustafa 13.06.2024 06:02

.cshtml и .cs добавлены в мой исходный пост.

MelB 13.06.2024 17:34

проверьте редактирование в моем ответе, я добавил решение для периодического обновления

hassaan mustafa 14.06.2024 07:07

Где бы я разместил этот фрагмент кода? СОЗДАТЬ ТРИГГЕР trip_trigger ПОСЛЕ ВСТАВКИ ИЛИ ОБНОВЛЕНИЯ ИЛИ УДАЛЕНИЯ ПРИ ОТКЛЮЧЕНИИ ДЛЯ КАЖДОЙ СТРОКИ ВЫПОЛНИТЬ ФУНКЦИЮ notify_trip_change(); Я понимаю, что остальное будет в отдельном файле класса, который я создаю, под названием «Программа». Поместится ли этот CREATE TRIGGER где-нибудь на страницах моего путешествия .cs? Индекс? Меня беспокоит, что если я выполню «периодические обновления», этот пользователь будет вводить данные и двигаться слишком быстро, чтобы составить отчет, поэтому он будет запущен до того, как он обновится. Извините, если я не ясно выразился. Я хотел бы, чтобы она обновлялась каждый раз при изменении таблицы Trip. Спасибо!

MelB 14.06.2024 15:05

проверьте Редактировать 2 в моем ответе

hassaan mustafa 15.06.2024 09:47

Другие вопросы по теме