Не удается сохранить несколько вариантов выбора в списке выбора - asp. net основные страницы веб-приложения. - PullRequest
0 голосов
/ 07 января 2020

Здесь я могу связать список множественного выбора на странице создания.

<select id="multiple" asp-for="SecurityLog.Officer" multiple="multiple" class="selectpicker form-control" asp-items="ViewBag.Officer">
</select>

public IActionResult OnGetAsync()
{                    
     ViewData["Officer"] = new SelectList(_context.Officer.Where(a => a.Active == "Y"), "ID", "FullName");

     return Page();
}

Самая большая проблема у меня заключается в том, что я пытаюсь редактировать / публиковать значения, и в моей модели нет прямого поля для привязки.

Multi-select binding

Я нашел хороший пример здесь, но он показывает только, как сохранить 1 выбор. https://www.learnrazorpages.com/razor-pages/forms/select-lists

Моя модель SecurityLog имеет это

public virtual Officer Officer { get; set; }

Моя модель сотрудника имеет это

namespace SecurityCore.Models
{
    public class Officer
    {
        [Required]
        public int ID { get; set; }

        [Required]
        [Display(Name = "Officer's First Name")]
        public string FirstName { get; set; }

        [Required]
        [Display(Name = "Officer's Last Name")]
        public string LastName { get; set; }

        [Display(Name = "Officer's Name")]
        public string FullName { get; set; }

        [Required]
        public string Active { get; set; }        
    }
}

У меня нет модели SecurityLogOfficer , Нужен ли мне один?

А вот моя схема базы данных и примеры результатов

Sql Database Schema

Любая помощь будет Будьте благодарны!

* ОБНОВЛЕНИЕ *

Спасибо за ваше предложение связать со списком и изменить asp для этого списка. Вот мой обновленный код. SelectedOfficerIds действительно сохраняет выбранные идентификаторы.

<select id="multiple" asp-for="SelectedOfficerIds" multiple="multiple" class="selectpicker form-control" asp-items="ViewBag.Officer">    
</select>

Я отправляю сообщения в две разные базы данных (1 запись должна go в SecurityLog и несколько в SecurityLogOfficer), но так как я вызываю savechanes () дважды, это фактически отправляя несколько записей в базу данных SecurityLog и на секунду для l oop save я получаю сообщение об ошибке

Невозможно вставить явное значение для столбца идентификации в таблице 'SecurityLogOfficer', когда для IDENTITY_INSERT установлено значение OFF

_context.SecurityLog.Add(SecurityLog);
//We need to ensure we have the ID of the newly posted event
_context.SaveChanges();

int tempSecurityLogID = SecurityLog.ID;

for (int i = 0; i < SelectedOfficerIds.Length; i++)
{                
     SecurityLogOfficer.SecurityLogID = tempSecurityLogID;
     SecurityLog = null;

     SecurityLogOfficer.OfficerID = SelectedOfficerIds[i];
     _context.SecurityLogOfficer.Add(SecurityLogOfficer);                
     await _context.SaveChangesAsync();
}            

Message = "Entry added successfully!";

Есть ли способ очистить _context для SecurityLog, чтобы я публиковал только один раз, и как мне решить проблему identity_insert? У базы данных SecurityLogOfficer уже есть идентификационная вставка.

Обновление 1/9/2020

@ XingZou - Спасибо за быстрый ответ. Я попытался выполнить ваши шаги, и все отлично сработало !!!

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

Вот моя модель редактирования страницы ...

[BindProperty] 
public MultiSelectList GetExistingSelectedOfficerIds { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)
{
    var i = _context.SecurityLogOfficer.Where(a => a.SecurityLogID == SecurityLog.ID);

        SecurityLogOfficers.AddRange(i);

        int[] GetExistingSelectedOfficerIds = new int[SecurityLogOfficers.Count];

        int itemCount = 0;
        foreach (var item in SecurityLogOfficers)
        {                
            GetExistingSelectedOfficerIds[itemCount] = item.OfficerID;
            itemCount++;
        }

        return Page();
}

Вот моя страница редактирования бритвы. ..

<select id="multiple" asp-for= "GetExistingSelectedOfficerIds" multiple="multiple" class="selectpicker form-control" asp-items="ViewBag.Officer">
</select>
<span asp-validation-for="GetExistingSelectedOfficerIds" class="text-danger"></span>

Ответы [ 2 ]

1 голос
/ 08 января 2020

Вам необходимо привязать выпадающий список к списку int вместо объекта.

В PageModel добавьте новое свойство, которое хранит все выбранные идентификаторы:

[BindProperty]
public int[] SelectedOfficerIds { get; set; }

На страницах Razor , Привязать множественный выбор к SelectedOfficerIds

<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="SecurityLog.EventDate" class="control-label"></label>
        <input asp-for="SecurityLog.EventDate" class="form-control" />
        <span asp-validation-for="SecurityLog.EventDate" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label class="control-label">Officers</label>
        <select id="multiple" asp-for="SelectedOfficerIds" multiple="multiple" class="selectpicker form-control" asp-items="ViewBag.Officer">
        </select>
    </div>

    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
    </div>
</form>

Когда вы отправляете форму, вы получите новый список удостоверений личности сотрудника SecurityLog в вашем почтовом обработчике.

Обновление 1 / 9/2020

Нет прямой связи между SecurityLog и сотрудником. Между SecurityLog и SecurityLogOfficer существует отношение один-ко-многим, а между SecurityLogOfficer и Officer - отношение многие-к-одному.

По вашему описанию это отношения многие-ко-многим между SecurityLog и Officer. 1.Удалите ID из SecurityLogOfficer, теперь он использует составной ключ

public class SecurityLogOfficer
{
    public int SecurityLogID { get; set; }
    public SecurityLog SecurityLog { get; set; }

    public int OfficerID { get; set; }
    public Officer Officer { get; set; }
}
public class Officer
{
    public int ID { get; set; }

    //other properties

    public List<SecurityLogOfficer> SecurityLogOfficers { get; set; }
}

public class SecurityLog
{
    public int ID { get; set; }

    //other properties

    public virtual List<SecurityLogOfficer> SecurityLogOfficers { get; set; }
}

2. Настройте отношение «многие ко многим», как показано ниже.

public class RazorpagesCoreContext : DbContext
{
    public RazorpagesCoreContext (DbContextOptions<RazorpagesCoreContext> options)
        : base(options)
    {
    }


    public DbSet<Officer> Officer { get; set; }
    public DbSet<SecurityLog> SecurityLog { get; set; }
    public DbSet<SecurityLogOfficer> SecurityLogOfficer { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<SecurityLogOfficer>()
            .HasKey(t => new { t.SecurityLogID, t.OfficerID });

        modelBuilder.Entity<SecurityLogOfficer>()
            .HasOne(pt => pt.SecurityLog)
            .WithMany(p => p.SecurityLogOfficers)
            .HasForeignKey(pt => pt.SecurityLogID);

        modelBuilder.Entity<SecurityLogOfficer>()
            .HasOne(pt => pt.Officer)
            .WithMany(t => t.SecurityLogOfficers)
            .HasForeignKey(pt => pt.OfficerID);
    }
}

3.Добавьте миграции и обновление базы данных.

Есть ли способ очистить _context для SecurityLog, чтобы я публиковал только один раз

4. В вашей PageModel сохраняйте данные, как показано ниже

[BindProperty]
public SecurityLog SecurityLog { get; set; }

public List<SecurityLogOfficer> SecurityLogOfficers { get; set; } = new List<SecurityLogOfficer>();

[BindProperty]
public int[] SelectedOfficerIds { get; set; }

public async Task<IActionResult> OnPostAsync()
    {
        _context.SecurityLog.Add(SecurityLog);
        foreach (var id in SelectedOfficerIds)
        {
            var item = new SecurityLogOfficer()
            {
                SecurityLog = SecurityLog,
                Officer = await _context.Officer.FirstOrDefaultAsync(s => s.ID == id),
            };
            SecurityLogOfficers.Add(item);
        }
        _context.SecurityLogOfficer.AddRange(SecurityLogOfficers);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }

Обновление 1/10/2020

Чтобы получить несколько выбранных значений на странице редактирования, используйте код ниже перед return Page() в обработчике получения

ViewData["Officer"] = new MultiSelectList(_context.Officers.Where(a => a.Active == "Y"), "ID", "FullName", GetExistingSelectedOfficerIds);
0 голосов
/ 07 января 2020

Вы не поделились своей полной страницей создания страницы. Есть ли у вас что-то вроде следующего:

public MultiSelectList Officer { get; set; }

Я полагаю, что вы сможете заполнить это информацией Офицера из модели Офицера.

...