Хранение данных между запросами в dbcontext - PullRequest
0 голосов
/ 28 декабря 2018

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

Каждый раз, когда элемент добавляется / извлекается из любого списка, я отправляю сообщение с кнопкой «Отправить» для определенного действия, например «CustomerSelected».Я делаю это, потому что мне нужно воссоздать дополнительные компоненты представления для добавленного элемента.В этих методах я хотел бы добавить добавленные объекты в контекст БД, поэтому при отправке я могу просто сказать SaveChanges() и не собирать все одним и тем же методом.Но в ядре .net core db-контекст предоставляется по запросу, и желательно, чтобы он оставался таким.В этом случае, как я могу хранить эти временные объекты сущности между запросами, чтобы позже, если кто-то решит отправить их, я могу сказать SaveChanges() или отказаться от них иным образом?

Я хотел бы иметь что-то вроде этого:

public IActionResult CustomerAdded(int customerId)
{
    var customer = _context.Customers.First(c => c.IdCustomer == customerId);
    var message = _context.Messages.First(m => m.IdMessage = _idMessage);
    message.Customers.Add(customer);
    return View();
}

public IActionResult ItemAdded(int itemId)
{
    var item = _context.Items.First(c => c.IdItem == itemId);
    var message = _context.Messages.First(m => m.IdMessage = _idMessage);
    message.Items.Add(item);
    return View();
}

public IActionResult Submit()
{
    _context.SaveChanges();
    return View();
}

Если это невозможно, я думал о добавлении отдельных элементов в каждый метод и сохранении их там, а затем отправляю последний конечный элемент.Но если кто-то закрывает свой браузер без отправки, то у меня в базе данных есть неполные данные.Мне бы пришлось выполнить какую-то работу, чтобы удалить их, а для такой простой задачи это слишком много.

Ответы [ 3 ]

0 голосов
/ 03 января 2019

А как насчет динамических форм с javascript и использованием type="hidden" или visibility, а затем отправкой всего сразу

Или использованием TempData с перенаправлениями и повторным использованием этих данных в других представлениях (формах) как input type="hidden"

Поток:

Form1 ->

Метод контроллера сохраняет данные в TempData и перенаправляет в представление Form2 / или ViewData и возвращает представление Form2?->

В Form2 есть TempData, вставленные в форму под скрытыми вводами ->

Отправить оба сразу

0 голосов
/ 04 января 2019

Печенье!

public class HomeController : Controller
{

public string Index()
{

    HttpCookie cookie = Request.Cookies["message"];
    Message message = null;
    string json = "";

    if (cookie == null)
    {
        message = new Message();
        json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(message);
        cookie = new HttpCookie("message", json);
    }
    Response.Cookies.Add(cookie);
    return json;
}

public string CustomerAdded(int id)
{
    HttpCookie cookie = Request.Cookies["message"];
    Message message = null;
    string json = "";

    if (cookie == null || string.IsNullOrEmpty(cookie.Value))
    {
        message = new Message();
        json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(message);
        cookie = new HttpCookie("message", json);
    }
    else
    {
        json = cookie.Value;
        message = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Message>(json);
    }

    if (message.Customers == null) message.Customers = new List<int>();
    if (message.Items == null) message.Items = new List<int>();

    if (!message.Customers.Contains(id))
    {
        message.Customers.Add(id);
    }


    json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(message);
    cookie = new HttpCookie("message", json);

    Response.Cookies.Add(cookie);

    return json;
}


public string ItemAdded(int id)
{
    HttpCookie cookie = Request.Cookies["message"];
    Message message = null;
    string json = "";

    if (cookie == null || string.IsNullOrEmpty(cookie.Value))
    {
        message = new Message();
        json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(message);
        cookie = new HttpCookie("message", json);
    }
    else
    {
        json = cookie.Value;
        message = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Message>(json);
    }
    if (message.Customers == null) message.Customers = new List<int>();
    if (message.Items == null) message.Items = new List<int>();

    if (!message.Items.Contains(id))
    {
        message.Items.Add(id);
    }

    json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(message);
    cookie = new HttpCookie("message", json);

    Response.Cookies.Add(cookie);

    return json;
}

public string Submit()
{
    HttpCookie cookie = Request.Cookies["message"];
    Message message = null;
    string json = "";

    if (cookie == null || string.IsNullOrEmpty(cookie.Value))
    {
        return "no data";
    }
    else
    {
        json = cookie.Value;
        message = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Message>(json);
    }

    Response.Cookies["message"].Value = "";
    Response.Cookies["message"].Expires = DateTime.Now.AddDays(-1);

    return "Submited";

}
}

Примеры ссылок

enter image description here enter image description here enter image description here enter image description here

0 голосов
/ 03 января 2019

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

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

Механизм отслеживания изменений на стороне клиента зависит от требований и сценария, например, вы можете отслеживать измененияиспользуя вводы html, вы можете отслеживать изменения, используя cookie, вы можете отслеживать изменения, используя объекты javascript в памяти браузера, такие как угловые сценарии.

В этом посте я покажу пример использования вводов html и привязки модели.Чтобы узнать больше об этой теме, взгляните на эту статью Phill Haack: Привязка модели к списку .

Пример

В следующем примере я опишу списокредактирование сценария для списка клиентов.Для простоты, я полагаю:

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

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

Отслеживаемый Модель

Этот класс является моделью, которая помогает нам в отслеживании на стороне клиента и редактировании списка:

public class Trackable<T>
{
    public Trackable() { }
    public Trackable(T model) { Model = model; }
    public Guid Index { get; set; } = Guid.NewGuid();
    public bool Deleted { get; set; }
    public bool Added { get; set; }
    public T Model { get; set; }
}

Модель клиента

Модель клиента:

public class Customer
{
    [Display(Name ="Id")]
    public int Id { get; set; }

    [StringLength(20, MinimumLength = 1)]
    [Required]
    [Display(Name ="First Name")]
    public string FirstName { get; set; }

    [StringLength(20, MinimumLength = 1)]
    [Required]
    [Display(Name ="Last Name")]
    public string LastName { get; set; }

    [EmailAddress]
    [Required]
    [Display(Name ="Email Name")]
    public string Email { get; set; }
}

Index.cshtml Представление

Представление Index отвечает за отображение List<Trackable<Customer>>.При рендеринге каждой записи мы используем RowTemplate view.То же представление, которое мы используем при добавлении нового элемента.

В этом представлении у нас есть кнопка отправки для сохранения и кнопка для добавления новых строк, которая вызывает действие Create с использованием ajax.

ЗдесьИндексное представление:

@model IEnumerable<Trackable<Customer>>
<h2>Index</h2>
<form method="post" action="Index">
    <p>
        <button id="create">New Customer</button>
        <input type="submit" value="Save All">
    </p>
    <table class="table" id="data">
        <thead>
            <tr>
                <th>
                    Delete
                </th>
                <th>
                    @Html.DisplayNameFor(x => x.Model.FirstName)
                </th>
                <th>
                    @Html.DisplayNameFor(x => x.Model.LastName)
                </th>
                <th>
                    @Html.DisplayNameFor(x => x.Model.Email)
                </th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                await Html.RenderPartialAsync("RowTemplate", item);
            }
        </tbody>
    </table>
</form>

@section Scripts{
    <script>
        $(function () {
            $('#create').click(function (e) {
                e.preventDefault();
                $.ajax({
                    url: 'Create',
                    method: 'Get',
                    success: function (data) {
                        $('#data tbody tr:last-child').after(data);
                    },
                    error: function (e) { alert(e); }
                });
            });
        });
    </script>
}

RowTemplate.cshtml Представление

Это представление отвечает за отображение записи клиента.В этом представлении мы сначала визуализируем Index в скрытом виде, затем устанавливаем префикс [index] для полей и затем визуализируем поля, включая индекс, добавленные, удаленные и идентификатор модели:

ВотRowTemplate View:

@model Trackable<Customer>
<tr>
    <td>
        @Html.HiddenFor(x => x.Index)
        @{Html.ViewData.TemplateInfo.HtmlFieldPrefix = $"[{Model.Index}]";}
        @Html.HiddenFor(x => x.Index)
        @Html.HiddenFor(x => x.Model.Id)
        @Html.HiddenFor(x => x.Added)
        @Html.CheckBoxFor(x => x.Deleted)
    </td>
    <td>
        @Html.EditorFor(x => x.Model.FirstName)
        @Html.ValidationMessageFor(x => x.Model.FirstName)
    </td>
    <td>
        @Html.EditorFor(x => x.Model.LastName)
        @Html.ValidationMessageFor(x => x.Model.LastName)
    </td>
    <td>
        @Html.EditorFor(x => x.Model.Email)
        @Html.ValidationMessageFor(x => x.Model.Email)
    </td>
</tr>

CustomerController

public class CustomerController : Controller
{
    private static List<Customer> list;
}

Он будет выполнять следующие действия.

[GET] Индекс Действие

В этом действии вы можете загрузить данные из базы данных и сформировать их в List<Trackable<Customer>> и передать в Index View:

[HttpGet]
public IActionResult Index()
{
    if (list == null)
    {
        list = Enumerable.Range(1, 5).Select(x => new Customer()
        {
            Id = x,
            FirstName = $"A{x}",
            LastName = $"B{x}",
            Email = $"A{x}@B{x}.com"
        }).ToList();
    }
    var model = list.Select(x => new Trackable<Customer>(x)).ToList();
    return View(model);
}

[GET] Создать действие

Это действие отвечает за возврат нового шаблона строки.Он будет вызываться кнопкой в ​​индексном представлении с использованием ajax:

[HttpGet]
public IActionResult Create()
{
    var model = new Trackable<Customer>(new Customer()) { Added = true };
    return PartialView("RowTemplate", model);
}

[POST] Индексное действие

Это действие отвечает заполучение отслеживаемого элемента от клиента и сохранение его.Модель, которую он получает, - List<Trackable<Customer>>.Сначала он удаляет сообщения об ошибках проверки удаленных строк.Затем удаляет те, которые как удалены, так и добавлены.Затем проверяет, действительно ли состояние модели, пытается применить изменения к источнику данных.

Элементы, имеющие Deleted свойство как true, удаляются, элементы, имеющие Added как true и Deleted как false, являются новыми элементами,а остальные пункты редактируются.Затем, без необходимости загружать все элементы из базы данных, просто используя цикл for, вызовите db.Entry для каждого элемента, установите их состояния и, наконец, сохраните изменения.

[HttpPost]
public IActionResult Index(List<Trackable<Customer>> model)
{
    //Cleanup model errors for deleted rows
    var deletedIndexes = model.
        Where(x => x.Deleted).Select(x => $"[{x.Index}]");
    var modelStateDeletedKeys = ModelState.Keys.
        Where(x => deletedIndexes.Any(d => x.StartsWith(d)));
    modelStateDeletedKeys.ToList().ForEach(x => ModelState.Remove(x));

    //Removing rows which are added and deleted
    model.RemoveAll(x => x.Deleted && x.Added);

    //If model state is not valid, return view
    if (!ModelState.IsValid)
        return View(model);

    //Deleted rows
    model.Where(x => x.Deleted && !x.Added).ToList().ForEach(x =>
    {
        var i = list.FindIndex(c => c.Id == x.Model.Id);
        if (i >= 0)
            list.RemoveAt(i);
    });

    //Added rows
    model.Where(x => !x.Deleted && x.Added).ToList().ForEach(x =>
    {
        list.Add(x.Model);
    });

    //Edited rows
    model.Where(x => !x.Deleted && !x.Added).ToList().ForEach(x =>
    {
        var i = list.FindIndex(c => c.Id == x.Model.Id);
        if (i >= 0)
            list[i] = x.Model;
    });

    //Reditect to action index
    return RedirectToAction("Index");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...