Script & CSS Регистрационный помощник в ASP.NET MVC?

Вы догадались, есть условие гонки.

  • Создание ограничения = сервер БД оценивает id=123 не существует до фиксации записи в таблице. (1 сервер => нет состояния гонки)
  • Используя WHERE - каждый клиент, независимо , проверяет, что id=123 не существует, прежде чем вставить запись в таблицу. (несколько клиентов, выполняющихся одновременно, помнят, что клиенты могут видеть записи только по состоянию на момент начала выполнения оператора => условие гонки)

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

1118 Тестирование - это не так сложно, как вы думаете. Попробуйте подключить 2 клиентов с одного компьютера.

Первый клиент :

create table ForceWait (val text);
with LetsWait as (
insert into ForceWait select null from pg_sleep(10)
) /*We want to make sure waiting and inserting are done in separate steps*/
insert into employee (id, name)
select 123,'joe' where not exists (select 1 from employee where id=123)

Второй клиент , немедленно выполнить:

insert into employee (id, name)
select 123,'jack' where not exists (select 1 from employee where id=123);
select * from Employee where id = 123

[1130 ] Результат : первый запрос запускается первым, но заканчивается последним.
Какое-то время вы увидите jack в таблице, но joe все равно будет вставлено. Вот ваше состояние гонки.

Если, как вы сказали, вы продолжаете вставлять / обновлять в таблице, то предложение WHERE быстро станет эквивалентом моего pg_sleep(...) выше.


PS: Вы можете подумать, что первый клиент мог выполнить что-то намного более простое:

insert into employee (id, name)
select 123,'joe' from pg_sleep(10) where not exists (select 1 from employee where id=123)

Однако, postgresql (по крайней мере, версия 11) может оптимизировать все это, если релевантный (попробуйте запрос, вы увидите, что он не ждет, когда id=123 уже существует).
Это означает, что у оптимизатора есть побочный эффект, который мы хотим избежать в целях тестирования.

PPS: не забудьте сбросить таблицу ForceWait

10
задан Samnang 26 November 2008 в 04:37
поделиться

7 ответов

Основной шаблон страницы по умолчанию включает Содержание PlaceHolder для головы. Если это не делает можно легко добавить тот:

<head runat="server">
    <title></title>
    <asp:ContentPlaceHolder ID="head" runat="server" />
</head>

Ваши представления могут затем поместить что-либо, что они хотят в голове:

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    <script src="Scripts/myScripts.js" type="text/javascript"></script>
    <link href="Styles/myStyles.css" rel="stylesheet" type="text/css" />
</asp:Content>
10
ответ дан 3 December 2019 в 18:36
поделиться

технически необходимо помещать весь js внизу страницы для лучшей производительности.

Я думаю единственный способ, которым Вы могли сделать это, хотя должен будет включать JavaScript в VIewData и отображать ViewData на masterpage (не отличное решение).

0
ответ дан 3 December 2019 в 18:36
поделиться

Похоже, пока нет простой опции, «встроенной» в каркас ASP.NET MVC. , Если вы используете пользовательский элемент управления (.ascx), которым вы, возможно, являетесь, если вы создаете автономные элементы управления, которые также хотят управлять своими собственными требованиями JavaScript, тогда вы даже не сможете использовать заполнители, чтобы помочь вам.

В конце концов, я создал вспомогательный класс, и в нем есть пара методов:

private static SortedList<int, string> GetRegisteredScriptIncludes()
{
    var registeredScriptIncludes = System.Web.HttpContext.Current.Items["RegisteredScriptIncludes"] as SortedList<int, string>;

    if (registeredScriptIncludes == null)
    {
        registeredScriptIncludes = new SortedList<int, string>();
        System.Web.HttpContext.Current.Items["RegisteredScriptIncludes"] = registeredScriptIncludes;
    }

    return registeredScriptIncludes;
}

public static void RegisterScriptInclude(this HtmlHelper htmlhelper, string script)
{
    var registeredScriptIncludes = GetRegisteredScriptIncludes();
    if (!registeredScriptIncludes.ContainsValue(script))
    {
        registeredScriptIncludes.Add(registeredScriptIncludes.Count, script);
    }
}

public static string RenderScripts(this HtmlHelper htmlhelper)
{
    var registeredScriptIncludes = GetRegisteredScriptIncludes();
    var scripts = new StringBuilder();
    foreach (string script in registeredScriptIncludes.Values)
    {
        scripts.AppendLine("<script src='" + script + "' type='text/javascript'></script>");
    }
    return scripts.ToString();
}

В любом случае, это базовая форма, чтобы попытаться показать, как он работает. Его можно улучшить многими способами, но в данный момент он просто отфильтровывает дубликаты запросов на вставку сценария для вас. Всякий раз, когда вы хотите добавить новый скрипт в ascx (или aspx в этом отношении), вы можете сделать это следующим образом:

<%
    Html.RegisterScriptInclude(Url.Content("~/Scripts/MapLayers/MapLayer.js"));
    Html.RegisterScriptInclude(Url.Content("~/Scripts/MapLayers/Vehicles.js"));
%>

Затем вам нужно помнить, чтобы вывести их, как только вы закончите. Это достигается с помощью следующего вызова в том месте на вашей странице, где вы хотите вывести теги сценария:

<%=Html.RenderScripts() %>

Кажется, пока что это работает для меня. Я почти ожидал, что возникнут проблемы с рендерингом, в зависимости от того, в какой момент был вызван RenderScripts, особенно если не все из RegisterScriptInclude были вызваны, но пока, похоже, это делает свою работу. Если вы делаете сценарии последними, у вас не должно быть проблем.

5
ответ дан 3 December 2019 в 18:36
поделиться

@Jason: ВНИМАНИЕ, вы не должны использовать подобные статические переменные ... В веб-контексте статические переменные используются совместно всеми пользователями и всеми запросами страниц. Я удивлен, что вы не столкнулись с проблемами со своим кодом. Принцип хорош, но код неверен и доставит вам проблемы. В этом случае вы должны использовать System.Web.HttpContext.Current.Items. См. http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx для получения дополнительной информации.

4
ответ дан 3 December 2019 в 18:36
поделиться

Вот решение, подобное тому, которое дал Джейсон, но учитывает комментарии vdh_ant:

http://frugalcoder.us/post/2009/06/29/Handling-Scripts -in-ASPNet-MVC.aspx

2
ответ дан 3 December 2019 в 18:36
поделиться

MVC Futures теперь имеет встроенные помощники для этого ...

1.<head>
2.    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
3.    <%= Html.Css("BlueTheme/site.css") %>
4.    <%= Html.Script("jquery-1.3.2.js") %>
5.</head>

Дополнительная информация здесь: http://blog.osbornm.com/archive/2009/10 /12/mvc-script-css-helpers.aspx

0
ответ дан 3 December 2019 в 18:36
поделиться

Мэтью,

Я просмотрел ваш блог о помощниках Html.Css и Html.Script. Я не хочу быть критичным, но я не вижу в блоге упоминания о том, как помощники Css и Script могут решить проблему, обсуждаемую здесь. Проблема здесь в том, что необходимо «зарегистрировать» ссылки на скрипты в любой момент в процессе рендеринга и, возможно, несколько раз (в случае шаблона или частичного представления, которое используется несколько раз и регистрирует свои собственные скрипты), а затем выводить совокупные результаты, без дубликатов, в одном месте.

Если ваше решение решает эту проблему, пожалуйста, исправьте меня некоторыми пояснениями.

- С уважением, Кен

0
ответ дан 3 December 2019 в 18:36
поделиться
Другие вопросы по тегам:

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