Имам нужда от насоки относно най-добрите практики.
Имам две SQL таблици, едната наречена Person whichсъдържа PersonId, PersonName и друга наричана категория, която съдържа CategoryId, CategoryName. Категориите могат да бъдат доста многобройни и да се добавят от време на време.
Искам изглед за създаване, който показва текстово поле за PersonName и след това едно квадратче за всяка от категориите в таблицата Категории.
Потребителят може да въведе име и да отбележи толкова квадратчета от категории, колкото желае, и след това да запази.
Правилен ли е подходът за вмъкване на PersonNameв таблицата Person и след това вмъкнете запис за всяка комбинация лице / категория в нова таблица, наречена PersonCategory, която има полета PersonId и CategoryId?
Ако направя това, как да се справя с актуализациите, ако категориите се променят в изгледа за редактиране? Това е категория, която може да бъде отменена срещу човек. Трябва ли записът в PersonCategory да бъде изтрит?
Отговори:
1 за отговор № 1Ето как го правя. Ще премина през следното.
- Преглед на модела
- ASP.NET MVC изглед (потребителски интерфейс)
- Метод за контрол след действие
- Алгоритъм за запазване
Преглед на модела
public class PersonViewModel
{
public int Id { get; set; }
public string PersonName { get; set; }
// For rendering Checkboxes in the MVC View
public IList<SelectListItem> CategoryCheckboxes { get; set; }
// For data binding on Postback (HTTP POST).
// <input type="checkbox" /> will have the same `name` attribute as this.
public IList<int> AssociatedCategories { get; set; }
}
ASP.NET MVC изглед
<div>Name: <%= Html.EditorFor( m => m.PersonName ) %></div>
<fieldset>
<legend>Associatied Categories</legend>
<% foreach (SelectListItem c in Model.CategoryCheckboxes) { %>
<!-- "name" attribute is same as the C# View Model property name -->
<%= Html.CheckBox( "AssociatedCategories", c.Selected, new Dictionary<string, object> { { "value", c.Value } } ); %>
<%= Html.Encode( c.Text ) %><br />
<% } %>
</fieldset>
Метод за действие на контролера
[HttpPost]
public ActionResult Edit(PersonViewModel viewModel)
{
Person p = personService.Update( viewModel ); // persist changes to DB
if (p == null) // person record doesn"t exist in DB
return RedirectToAction("NotFound");
return RedirectToAction("Edit", new { id = viewModel.Id });
}
Алгоритъм за запазване
// this is in the `PersonService` class.
public void Update(PersonViewModel viewModel)
{
Person p = personRepository.GetByPrimaryKey( viewModel.Id );
if (p == null)
return null;
p.PersonName = viewModel.PersonName;
IList<int> existingAssociatedCategories = GetAssociatedCategories( p.PersonId );
foreach( int i in viewModel.AssociatedCategories )
{
if (!existingAssociatedCategories.Contains( i ))
Associate( p.PersonId, i ); // add NEW association in DB
}
foreach( int k in existingAssociatedCategories)
{
if (!viewModel.AssociatedCategories.Contains( k ))
DeleteAssociation( p.PersonId, k ); // delete existing association
}
repository.UpdatePerson( p ); // save changes to DB for Person object
return p;
}
Позволете ми да знаете, ако имате някакви въпроси.
3 за отговор № 2
Обикновено за подобно нещо бих се въздържал от АКТУАЛИЗАЦИИ. Бих изтрил всички записи за дадено лице от PersonCategory
и след това поставете отново тези, които се записват PersonCategory
.
1 за отговор № 3
Отговорите на вашите въпроси са да, добавете / изтрийте ги там, където са добавени / премахнати и да.
Това е връзка много към много, която се представя релационно с помощта на таблица на връзките.
1 за отговор № 4
Ето как го правя. Ще премина през следното.
- Преглед на модела
- ASP.NET MVC изглед (потребителски интерфейс)
- Метод за контрол след действие
- Алгоритъм за запазване
Преглед на модела
public class PersonViewModel
{
public int Id { get; set; }
public string PersonName { get; set; }
// For rendering Checkboxes in the MVC View
public IList<SelectListItem> CategoryCheckboxes { get; set; }
// For data binding on Postback (HTTP POST).
// <input type="checkbox" /> will have the same `name` attribute as this.
public IList<int> AssociatedCategories { get; set; }
}
ASP.NET MVC изглед
<div>Name: <%= Html.EditorFor( m => m.PersonName ) %></div>
<fieldset>
<legend>Associatied Categories</legend>
<% foreach (SelectListItem c in Model.CategoryCheckboxes) { %>
<!-- "name" attribute is same as the C# View Model property name -->
<%= Html.CheckBox( "AssociatedCategories", c.Selected, new Dictionary<string, object> { { "value", c.Value } } ); %>
<%= Html.Encode( c.Text ) %><br />
<% } %>
</fieldset>
Метод за действие на контролера
[HttpPost]
public ActionResult Edit(PersonViewModel viewModel)
{
Person p = personService.Update( viewModel ); // persist changes to DB
if (p == null) // person record doesn"t exist in DB
return RedirectToAction("NotFound");
return RedirectToAction("Edit", new { id = viewModel.Id });
}
Алгоритъм за запазване
// this is in the `PersonService` class.
public void Update(PersonViewModel viewModel)
{
Person p = personRepository.GetByPrimaryKey( viewModel.Id );
if (p == null)
return null;
p.PersonName = viewModel.PersonName;
IList<int> existingAssociatedCategories = GetAssociatedCategories( p.PersonId );
foreach( int i in viewModel.AssociatedCategories )
{
if (!existingAssociatedCategories.Contains( i ))
Associate( p.PersonId, i ); // add NEW association in DB
}
foreach( int k in existingAssociatedCategories)
{
if (!viewModel.AssociatedCategories.Contains( k ))
DeleteAssociation( p.PersonId, k ); // delete existing association
}
repository.UpdatePerson( p ); // save changes to DB for Person object
return p;
}
Позволете ми да знаете, ако имате някакви въпроси.
3 за отговор № 5
Обикновено за подобно нещо бих се въздържал от АКТУАЛИЗАЦИИ. Бих изтрил всички записи за дадено лице от PersonCategory
и след това поставете отново тези, които се записват PersonCategory
.
1 за отговор № 6
Отговорите на вашите въпроси са да, добавете / изтрийте ги там, където са добавени / премахнати и да.
Това е връзка много към много, която се представя релационно с помощта на таблица на връзките.