无法在 select 列表中保存多个 selection - asp.net 核心网络应用剃刀页面
Can't save multiple selections in select list - asp.net core web app razor pages
在这里,我可以在创建页面上绑定多select select列表。
<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();
}
我遇到的最大问题是我正在尝试 edit/post 值,但在我的模型中没有可绑定的直接字段。
我在这里找到了一个很好的例子,但它只告诉你如何节省 1 个 selection。
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 模型。我需要一个吗?
这是我的数据库架构和示例结果
如有任何帮助,我们将不胜感激!
* 更新 *
感谢您建议绑定到列表并将 asp-for 更改为该列表。这是我更新的代码。 SelectedOfficerIds 确实存储了 selected id。
<select id="multiple" asp-for="SelectedOfficerIds" multiple="multiple" class="selectpicker form-control" asp-items="ViewBag.Officer">
</select>
我正在 post访问两个不同的数据库(1 条记录应该转到 SecurityLog,多条记录应该转到 SecurityLogOfficer),但是由于我调用了 savechanes() 两次,它实际上是 post 多个记录到 SecurityLog 数据库并在第二个 for 循环保存时收到错误
Cannot insert explicit value for identity column in table 'SecurityLogOfficer' when IDENTITY_INSERT is set to 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!";
有没有办法清除 SecurityLog 的 _context,所以我只 post 一次,如何解决 identity_insert 问题?数据库 SecurityLogOfficer 已经有身份插入。
2020 年 1 月 9 日更新
@XingZou - 感谢您的快速回复。我尝试执行您的步骤并且一切顺利!!!
如果您不介意,我还有一个问题?我试图在编辑页面上获取 selected 值的列表,但无法设置这些值。这是我到目前为止尝试过的...
这是我的编辑页面模型...
[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>
您没有分享完整的创建页面模型。里面有没有类似下面的东西:
public MultiSelectList Officer { get; set; }
我相信您将能够使用 Officer 模型中的 Officer 信息填充它。
您需要将下拉列表绑定到一个 int 列表而不是 object。
在 PageModel 中,添加一个新的 属性 来存储所有 selected ID:
[BindProperty]
public int[] SelectedOfficerIds { get; set; }
在Razor Pages上,绑定多个select到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>
当您提交表单时,您将在您的 post 处理程序中获得 SecurityLog 的新官员 ID 列表。
2020 年 1 月 9 日更新
There is no direct relationship between SecurityLog and Officer. There is a one-to-many relationship between SecurityLog and SecurityLogOfficer and a many-to-one relationship between SecurityLogOfficer and Officer.
根据你的描述,many-to-many relationships介于SecurityLog
和Officer
之间。
1.RemoveSecurityLogOfficer
的ID
,现在使用复合键
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.Configure 如下所示的多对多关系。
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.Add 迁移和更新数据库。
Is there a way to clear out _context for SecurityLog so I only post once
4.In你的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");
}
2020 年 1 月 10 日更新
要在编辑页面中获取多个 selected 值,请在获取处理程序return Page()
之前使用以下代码
ViewData["Officer"] = new MultiSelectList(_context.Officers.Where(a => a.Active == "Y"), "ID", "FullName", GetExistingSelectedOfficerIds);
在这里,我可以在创建页面上绑定多select select列表。
<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();
}
我遇到的最大问题是我正在尝试 edit/post 值,但在我的模型中没有可绑定的直接字段。
我在这里找到了一个很好的例子,但它只告诉你如何节省 1 个 selection。 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 模型。我需要一个吗?
这是我的数据库架构和示例结果
如有任何帮助,我们将不胜感激!
* 更新 *
感谢您建议绑定到列表并将 asp-for 更改为该列表。这是我更新的代码。 SelectedOfficerIds 确实存储了 selected id。
<select id="multiple" asp-for="SelectedOfficerIds" multiple="multiple" class="selectpicker form-control" asp-items="ViewBag.Officer">
</select>
我正在 post访问两个不同的数据库(1 条记录应该转到 SecurityLog,多条记录应该转到 SecurityLogOfficer),但是由于我调用了 savechanes() 两次,它实际上是 post 多个记录到 SecurityLog 数据库并在第二个 for 循环保存时收到错误
Cannot insert explicit value for identity column in table 'SecurityLogOfficer' when IDENTITY_INSERT is set to 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!";
有没有办法清除 SecurityLog 的 _context,所以我只 post 一次,如何解决 identity_insert 问题?数据库 SecurityLogOfficer 已经有身份插入。
2020 年 1 月 9 日更新
@XingZou - 感谢您的快速回复。我尝试执行您的步骤并且一切顺利!!!
如果您不介意,我还有一个问题?我试图在编辑页面上获取 selected 值的列表,但无法设置这些值。这是我到目前为止尝试过的...
这是我的编辑页面模型...
[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>
您没有分享完整的创建页面模型。里面有没有类似下面的东西:
public MultiSelectList Officer { get; set; }
我相信您将能够使用 Officer 模型中的 Officer 信息填充它。
您需要将下拉列表绑定到一个 int 列表而不是 object。
在 PageModel 中,添加一个新的 属性 来存储所有 selected ID:
[BindProperty]
public int[] SelectedOfficerIds { get; set; }
在Razor Pages上,绑定多个select到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>
当您提交表单时,您将在您的 post 处理程序中获得 SecurityLog 的新官员 ID 列表。
2020 年 1 月 9 日更新
There is no direct relationship between SecurityLog and Officer. There is a one-to-many relationship between SecurityLog and SecurityLogOfficer and a many-to-one relationship between SecurityLogOfficer and Officer.
根据你的描述,many-to-many relationships介于SecurityLog
和Officer
之间。
1.RemoveSecurityLogOfficer
的ID
,现在使用复合键
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.Configure 如下所示的多对多关系。
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.Add 迁移和更新数据库。
Is there a way to clear out _context for SecurityLog so I only post once
4.In你的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");
}
2020 年 1 月 10 日更新
要在编辑页面中获取多个 selected 值,请在获取处理程序return Page()
之前使用以下代码
ViewData["Officer"] = new MultiSelectList(_context.Officers.Where(a => a.Active == "Y"), "ID", "FullName", GetExistingSelectedOfficerIds);