Я не уверен, с чего начать. У меня есть таблица базы данных 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 больше полей.





Ваше решение не поддерживает живое соединение с исходными источниками данных. Это означает, что если базовые данные в таблице Trip изменятся, эти изменения не отразятся автоматически в вашем отчете. Чтобы гарантировать, что ваш отчет отражает все изменения, внесенные в таблицу Trip, вам необходимо повторно запрашивать данные каждый раз, когда вы создаете отчет.
или если вы хотите динамически обновлять отчет при обновлении таблицы, для этого вы можете:
- Периодическое обновление отчета: (событие опроса) Для этого вы можете создать функцию, которая вызывается через небольшие промежутки времени и повторно генерирует отчет или обновляет часть отчета: (пример кода)
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);
}
}
- Обновить отчет об обновлении таблицы поездок: Для этого вы можете создать триггер и функцию базы данных, которые будут уведомлять об обновлении таблицы, и вы можете фиксировать это событие и соответствующим образом обновлять свой отчет:
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>
РЕДАКТИРОВАТЬ Чтобы продолжить обновление отчета о подходе к обновлению таблицы отключений:
Создайте триггер и функцию PostgreSQL в среде вашей базы данных с помощью запросов, упомянутых выше.
Установите пакет SignalR:
dotnet добавить пакет Microsoft.AspNetCore.SignalR
Создайте хаб для управления общением с клиентами:
использование Microsoft.AspNetCore.SignalR; использование System.Threading.Tasks;
общедоступный класс TripChangeHub: Hub { общедоступная асинхронная задача NotifyTripChange() { await Clients.All.SendAsync("TripChanged"); } }
Настройте SignalR в Startup.cs:
публичный класс стартапа { общественная недействительность ConfigurationServices (службы IServiceCollection) { услуги.AddSignalR(); услуги.AddSingleton(); }
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSignalR(routes =>
{
routes.MapHub<TripChangeHub>("/tripChangeHub");
});
}
}
Измените фоновую службу для использования 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
}
}
Настройте интерфейс для прослушивания уведомлений.
Надеюсь это поможет
Как вы визуализируете свой отчет, можете ли вы поделиться этим кодом/классом?
.cshtml и .cs добавлены в мой исходный пост.
проверьте редактирование в моем ответе, я добавил решение для периодического обновления
Где бы я разместил этот фрагмент кода? СОЗДАТЬ ТРИГГЕР trip_trigger ПОСЛЕ ВСТАВКИ ИЛИ ОБНОВЛЕНИЯ ИЛИ УДАЛЕНИЯ ПРИ ОТКЛЮЧЕНИИ ДЛЯ КАЖДОЙ СТРОКИ ВЫПОЛНИТЬ ФУНКЦИЮ notify_trip_change(); Я понимаю, что остальное будет в отдельном файле класса, который я создаю, под названием «Программа». Поместится ли этот CREATE TRIGGER где-нибудь на страницах моего путешествия .cs? Индекс? Меня беспокоит, что если я выполню «периодические обновления», этот пользователь будет вводить данные и двигаться слишком быстро, чтобы составить отчет, поэтому он будет запущен до того, как он обновится. Извините, если я не ясно выразился. Я хотел бы, чтобы она обновлялась каждый раз при изменении таблицы Trip. Спасибо!
проверьте Редактировать 2 в моем ответе
Да, это то, что я ищу. Всего несколько вопросов. Я не совсем уверен, где мне разместить этот код? Проводится ли периодический опрос на самом Report.cs? Куда пойдет триггерный код отключения, если я захочу это сделать? У меня есть индекс поездки, создание, редактирование и удаление файлов .cs. Или это просто в отдельном файле класса? Я думаю, что, поскольку таблица Trip обновляется несколько раз в день, я хочу обновлять отчет каждый раз, когда происходит обновление. Процедура пользователя заключается в вводе данных и последующей печати отчета, поэтому, если он не обновился вовремя, это проблема.