Я работаю над приложением mvc для отображения данных в реальном времени (используя IIS-сервер), мне нужно работать с EF и signalR (что я довольно новичок в этих двух), программное обеспечение работает отлично, за исключением одной части, где Мне приходится перезагружать данные с SQL Server каждую секунду (всякий раз, когда изменяется БД), можно изменить до 70 строк (но обычно около 40).
Это работает, но когда я проверяю рабочий процесс IIS, использование памяти продолжает расти без освобождения, независимо от того, что я пытался ... Он использует JS для перезагрузки этой части, и кажется, что проблема (даже для меня это не похоже на правильный способ сделать это), но я не могу найти другой путь.
Я уже пытался принудительно установить соединение / разъединение, GC, кажется, делает свою работу, я знаю, что могу работать с сервером IIS, чтобы перезапустить приложение пула и ограничить использование памяти, но это не решает проблему. Я знаю, что проблема возникает из-за перезагрузки в частичном представлении, но я заблокирован.
Надеюсь, вы, ребята, можете помочь.
Модель
(Модель довольно проста только с некоторыми расчетами вроде)
public decimal TRS_EQ
{
get
{
if (pcs_theoriques_eq != " " && pcs_theoriques_eq != "" && pcs_theoriques_eq != null)
{
long theoEq = Convert.ToInt64(pcs_theoriques_eq);
if (pcs_bonnes_eq != null && pcs_bonnes_eq != " " && pcs_bonnes_eq != "" && theoEq != 0)
{
return Convert.ToDecimal(pcs_bonnes_eq) / theoEq * 100;
}
}
return 0.0m;
}
}
Контроллер
private IQueryable<TempsReel> collection;
public ActionResult IndexPartial()
{
Response.Cache.SetNoStore();
Response.Cache.SetNoServerCaching();
using (var db = new SignalRTestContext())
{
collection = from g in db.TempsReels select g;
collection = collection.OrderBy(g => g.groupe_machine);
ViewBag.NotifierEntity = db.GetNotifierEntity<TempsReel>(collection).ToJson();
ViewBag.IdMachine = Variables.idMachine;
ViewBag.Count = Variables.ListCatArrets.Count();
ViewBag.NomCategorie = Variables.ListCatArrets.Select(c => c.arretcatName).ToList();
ViewBag.Color = Variables.ListCatArrets.Select(c => c.arretcatColor).ToList();
collection = ArretTempsReel.OrganiseListParGroupe(collection);
GC.Collect();
db.Dispose();
return PartialView(collection.ToList());
}
}
Просмотр (перезагрузка только частичного просмотра)
<div id="tbTempsReelMachines">
@{ Html.RenderPartial("IndexPartial", Model); }
</div>
@section scripts
{
<script src="~/Scripts/jquery.signalR-2.4.0.min.js"></script>
<script src="~/signalr/hubs"></script>
<script type="text/javascript">
var signalRHubInitialized = false;
$(function ()
{
InitializeSignalRHubStore();
});
function InitializeSignalRHubStore()
{
if (signalRHubInitialized)
return;
try
{
var clientHub = $.connection.tempsReelArretHub;
clientHub.client.broadcastMessage = function (message)
{
if (message === "Refresh")
{
ReloadIndexPartial();
}
};
$.connection.hub.start().done(function ()
{
clientHub.server.initialize($("#NotifierEntity").val());
signalRHubInitialized = true;
});
} catch (err) {
signalRHubInitialized = false;
}
};
function ReloadIndexPartial()
{
$.post('@(Url.Action("IndexPartial",
"TempsReels", null, Request.Url.Scheme))')
.done(function (response)
{
$("#tbTempsReelMachines").html(response)
if (!signalRHubInitialized)
InitializeSignalRHubStore();
});
$("#tbTempsReelMachines").end();
};
</script>
}
ViewModel (для организации данных)
public class ArretTempsReel
{
public static IQueryable<TempsReel> OrganiseListParGroupe(IQueryable<TempsReel> InputList)
{
List<string> Groupe = InputList.Select(g => g.groupe_machine).Distinct().ToList();
List<TempsReel> L = new List<TempsReel>();
foreach (var item in Groupe)
{
var l = InputList.Where(f => f.groupe_machine == item).ToList();
L.AddRange(l);
TempsReel SP = new TempsReel();
SP = SommePartielle(l);
L.Add(SP);
}
return L.AsQueryable<TempsReel>();
}
public static TempsReel SommePartielle(List<TempsReel> InputList)
{
TempsReelClone TC = new TempsReelClone();
try
{
foreach (var item in InputList)
{
TC.pcs_bonnes_eq += (item.pcs_bonnes_eq != null) ? Convert.ToInt64(item.pcs_bonnes_eq) : 0;
TC.pcs_bonnes_j += (item.pcs_bonnes_j != null) ? Convert.ToInt64(item.pcs_bonnes_j) : 0;
TC.pcs_bonnes_of += (item.pcs_bonnes_of != null) ? Convert.ToInt64(item.pcs_bonnes_of) : 0;
TC.pcs_mauvaises_eq += (item.pcs_mauvaises_eq != null) ? Convert.ToInt64(item.pcs_mauvaises_eq) : 0;
TC.pcs_mauvaises_j += (item.pcs_mauvaises_j != null) ? Convert.ToInt64(item.pcs_mauvaises_j) : 0;
TC.pcs_mauvaises_of += (item.pcs_mauvaises_of != null) ? Convert.ToInt64(item.pcs_mauvaises_of) : 0;
TC.pcs_theoriques_eq += (item.pcs_theoriques_eq != null) ? Convert.ToInt64(item.pcs_theoriques_eq) : 0;
TC.pcs_theoriques_j += (item.pcs_theoriques_j != null) ? Convert.ToInt64(item.pcs_theoriques_j) : 0;
TC.pcs_theoriques_of += (item.pcs_theoriques_of != null) ? Convert.ToInt64(item.pcs_theoriques_of) : 0;
}
return new TempsReel
{
pcs_bonnes_eq = TC.pcs_bonnes_eq.ToString(),
pcs_bonnes_j = TC.pcs_bonnes_j.ToString(),
pcs_bonnes_of = TC.pcs_bonnes_of.ToString(),
pcs_mauvaises_eq = TC.pcs_mauvaises_eq.ToString(),
pcs_mauvaises_j = TC.pcs_mauvaises_j.ToString(),
pcs_mauvaises_of = TC.pcs_mauvaises_of.ToString(),
pcs_theoriques_eq = TC.pcs_theoriques_eq.ToString(),
pcs_theoriques_j = TC.pcs_theoriques_j.ToString(),
pcs_theoriques_of = TC.pcs_theoriques_of.ToString(),
nom_machine = "TOTAL GROUPE",
categorie = "",
nom_arret = ""
};
}
catch (Exception)
{
return null;
}
}
1024 * Hub *
public class TempsReelHub : Hub
{
internal NotifierEntity NotifierEntity { get; private set; }
public void DispatchToClient()
{
Clients.All.broadcastMessage("Refresh");
}
public void Initialize(String value)
{
NotifierEntity = NotifierEntity.FromJson(value);
if (NotifierEntity == null)
return;
Action<String> dispatcher = (t) => { DispatchToClient(); };
PushSqlDependency.Instance(NotifierEntity, dispatcher);
}
}
Уведомитель об изменении SQL
public class SqlDependencyRegister
{
public event SqlNotificationEventHandler SqlNotification;
readonly NotifierEntity notificationEntity;
internal SqlDependencyRegister(NotifierEntity notificationEntity)
{
this.notificationEntity = notificationEntity;
RegisterForNotifications();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security",
"CA2100:Review SQL queries for security vulnerabilities")]
void RegisterForNotifications()
{
using (var sqlConnection = new SqlConnection(notificationEntity.SqlConnectionString))
{
using (var sqlCommand = new SqlCommand(notificationEntity.SqlQuery, sqlConnection))
{
foreach (var sqlParameter in notificationEntity.SqlParameters)
sqlCommand.Parameters.Add(sqlParameter);
sqlCommand.Notification = null;
var sqlDependency = new SqlDependency(sqlCommand);
sqlDependency.OnChange += OnSqlDependencyChange;
if (sqlConnection.State == ConnectionState.Closed)
{
sqlConnection.Open();
}
sqlCommand.ExecuteNonQuery();
//sqlCommand.Parameters.Clear();
sqlConnection.Close();
}
}
}
void OnSqlDependencyChange(object sender, SqlNotificationEventArgs e)
{
SqlNotification?.Invoke(sender, e);
RegisterForNotifications();
}
}