带有 UserId 的 MVC Core SelectList 并加入另一个 table
MVC Core SelectList with UserId and Join to another table
我搜索了大量答案并尝试了多种编码方法。目前我得到
System.Data.Entity.Core.EntityCommandExecutionException: 'The data reader has more than one field. Multiple fields are not valid for EDM primitive or enumeration types.'
我的部分观点。
我想学这个,所以我花了最后 40 个小时研究和尝试不同的方法。我终于大声呼救了。
我只是想要一个包含所有这些的下拉框:
[Key] UserId - all user Id's taken from Identity Model
value = Users.LastName + ', ' + Users.FirstName + ' - Council: ' + CAST(Groups.CouncilNumber AS VARCHAR) + ', ' + UnitTypes.Name + ' ' + CAST(Groups.UnitNumber AS VARCHAR)
所以我可以为客户记录分配一个 UserId。需要显示 以便用户有足够的信息 select 正确的 UserId。
Linqer 给了我这个来代替我的 SQL。即使在用 ApplicationUser 替换 db.AspnetUsers 之后,我似乎也无法让它工作。
var query =
from Users in db.AspNetUsers
join Groups in db.Groups on new { GroupId = Convert.ToInt32(Users.GroupId) } equals new { GroupId = Groups.GroupId }
join UnitTypes in db.UnitTypes on Groups.UnitTypeId equals UnitTypes.UnitTypeId
orderby
Users.LastName,
Users.FirstName
select new {
Users.Id,
FullDescription = (Users.LastName + ", " + Users.FirstName + " - Council: " + Convert.ToString(Groups.CouncilNumber) + ", " + UnitTypes.Name + " " + Convert.ToString(Groups.UnitNumber))
};
foreach (var r in query)
Add(new AspNetUser(
r.Id, r.FullDescription))
这是我的设置:
public class CustomerViewModel : DbContext{
public CustomerViewModel(): base("name=CustomerViewModel"){ }
[Key]
public int CustomerId { get; set; }
[Required(ErrorMessage = "Please enter your first name.")]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your last name.")]
[StringLength(100)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[MaxLength(128), ForeignKey("ApplicationUser")]
public string UserId { get; set; }
public SelectList UserSelectList { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
}
namespace WOA.Models {
public class ApplicationUser : IdentityUser {
[Required(ErrorMessage = "Please enter your first name.")]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your last name.")]
[StringLength(100)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
public int? GroupId { get; set; }
public int CustomerId { get; set; }
[ForeignKey("GroupId")]
public virtual Group Group { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
}
namespace WOA.Models {
public class Group {
public int GroupId { get; set; }
public int CouncilNumber { get; set; }
public int UnitTypeId { get; set; }
public string UnitNumber { get; set; }
[ForeignKey("UnitTypeId")]
public virtual UnitType UnitType { get; set; }
}
}
namespace WOA.Models{
public class UnitType{
public int UnitTypeId { get; set; }
[Required] public string Name { get; set; }
}
}
namespace WOA.Controllers {
public class CustomersController : Controller {
private CustomerViewModel MapToViewModel(Models.Customer customer) {
CustomerViewModel customerVm = new CustomerViewModel() {
CustomerId = customer.CustomerId,
GroupId = customer.GroupId
};
return customerVm;
}
public ActionResult Edit(int customerId){
CustomerViewModel customerViewModel = MapToViewModel(customer);
customerViewModel.UserSelectList = GetUserGroupList(DbContext);
if (Request.IsAjaxRequest())
{
return PartialView("_CustomerEditPartial", customerViewModel);
}
return PartialView("_CustomerEditPartial", customerViewModel);
}
public SelectList GetUserGroupList(DbContext _dbContext) {
var sql = @"SELECT Users.Id as Value
, Users.LastName + ', ' + Users.FirstName + ' - Council: ' + CAST(Groups.CouncilNumber AS VARCHAR) + ', ' + UnitTypes.Name + ' ' + CAST(Groups.UnitNumber AS VARCHAR) AS Text
FROM dbo.AspNetUsers AS Users
JOIN dbo.Groups ON Users.GroupId = dbo.Groups.GroupId
JOIN dbo.UnitTypes ON dbo.Groups.UnitTypeId = dbo.UnitTypes.UnitTypeId
Order by Users.LastName, Users.FirstName ";
var kk = _dbContext.Database.SqlQuery<string>(sql);
SelectList mySl = new SelectList(kk, "Value", "Text");
return mySl;
}
}
}
@model WOA.ViewModels.CustomerViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CustomerViewModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.CustomerId)
<div class="form-group">
@Html.LabelFor(model => model.UserId, "UserId", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.UserId, ViewData.Model.UserSelectList, "Select One", new { @class = "form-control" })
@*@Html.DropDownListFor(model => model.UserId, new SelectList(Model.UserSelectList, "Value", "Text"), htmlAttributes: new { @class = "form-control", id = "UserId" })*@
@Html.ValidationMessageFor(model => model.UserId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
异常消息很明显:来自 EF return 的 SQL 数据 reader(SqlQuery
方法)超过单个值(即 Users.Id
和来自多列的连接字符串)。
此查询 returns Value
& Text
结果集中的列别名,而 SqlQuery
的 return 类型应该是单个 string
:
var sql = @"SELECT Users.Id as Value,
Users.LastName + ', ' + Users.FirstName + ' - Council: ' + CAST(Groups.CouncilNumber AS VARCHAR) + ', ' + UnitTypes.Name + ' ' + CAST(Groups.UnitNumber AS VARCHAR) AS Text
FROM dbo.AspNetUsers AS Users
JOIN dbo.Groups ON Users.GroupId = dbo.Groups.GroupId
JOIN dbo.UnitTypes ON dbo.Groups.UnitTypeId = dbo.UnitTypes.UnitTypeId
Order by Users.LastName, Users.FirstName ";
要解决此问题,请尝试创建额外的 class,其中包含 2 个对应于文本和值属性的属性,例如 SelectListItem
具有:
public class QueryResults
{
public string Value { get; set; } // change to int if Users.Id has integer value
public string Text { get; set; }
}
然后,将查询结果绑定到指定的视图模型中,然后创建List<SelectListItem>
:
var kk = _dbContext.Database.SqlQuery<QueryResults>(sql).ToList();
SelectList mySl = new SelectList(kk, "Value", "Text");
可以找到类似的问题 。
我搜索了大量答案并尝试了多种编码方法。目前我得到
System.Data.Entity.Core.EntityCommandExecutionException: 'The data reader has more than one field. Multiple fields are not valid for EDM primitive or enumeration types.'
我的部分观点。
我想学这个,所以我花了最后 40 个小时研究和尝试不同的方法。我终于大声呼救了。
我只是想要一个包含所有这些的下拉框:
[Key] UserId - all user Id's taken from Identity Model
value = Users.LastName + ', ' + Users.FirstName + ' - Council: ' + CAST(Groups.CouncilNumber AS VARCHAR) + ', ' + UnitTypes.Name + ' ' + CAST(Groups.UnitNumber AS VARCHAR)
所以我可以为客户记录分配一个 UserId。需要显示 以便用户有足够的信息 select 正确的 UserId。
Linqer 给了我这个来代替我的 SQL。即使在用 ApplicationUser 替换 db.AspnetUsers 之后,我似乎也无法让它工作。
var query =
from Users in db.AspNetUsers
join Groups in db.Groups on new { GroupId = Convert.ToInt32(Users.GroupId) } equals new { GroupId = Groups.GroupId }
join UnitTypes in db.UnitTypes on Groups.UnitTypeId equals UnitTypes.UnitTypeId
orderby
Users.LastName,
Users.FirstName
select new {
Users.Id,
FullDescription = (Users.LastName + ", " + Users.FirstName + " - Council: " + Convert.ToString(Groups.CouncilNumber) + ", " + UnitTypes.Name + " " + Convert.ToString(Groups.UnitNumber))
};
foreach (var r in query)
Add(new AspNetUser(
r.Id, r.FullDescription))
这是我的设置:
public class CustomerViewModel : DbContext{
public CustomerViewModel(): base("name=CustomerViewModel"){ }
[Key]
public int CustomerId { get; set; }
[Required(ErrorMessage = "Please enter your first name.")]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your last name.")]
[StringLength(100)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[MaxLength(128), ForeignKey("ApplicationUser")]
public string UserId { get; set; }
public SelectList UserSelectList { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
}
namespace WOA.Models {
public class ApplicationUser : IdentityUser {
[Required(ErrorMessage = "Please enter your first name.")]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your last name.")]
[StringLength(100)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
public int? GroupId { get; set; }
public int CustomerId { get; set; }
[ForeignKey("GroupId")]
public virtual Group Group { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
}
namespace WOA.Models {
public class Group {
public int GroupId { get; set; }
public int CouncilNumber { get; set; }
public int UnitTypeId { get; set; }
public string UnitNumber { get; set; }
[ForeignKey("UnitTypeId")]
public virtual UnitType UnitType { get; set; }
}
}
namespace WOA.Models{
public class UnitType{
public int UnitTypeId { get; set; }
[Required] public string Name { get; set; }
}
}
namespace WOA.Controllers {
public class CustomersController : Controller {
private CustomerViewModel MapToViewModel(Models.Customer customer) {
CustomerViewModel customerVm = new CustomerViewModel() {
CustomerId = customer.CustomerId,
GroupId = customer.GroupId
};
return customerVm;
}
public ActionResult Edit(int customerId){
CustomerViewModel customerViewModel = MapToViewModel(customer);
customerViewModel.UserSelectList = GetUserGroupList(DbContext);
if (Request.IsAjaxRequest())
{
return PartialView("_CustomerEditPartial", customerViewModel);
}
return PartialView("_CustomerEditPartial", customerViewModel);
}
public SelectList GetUserGroupList(DbContext _dbContext) {
var sql = @"SELECT Users.Id as Value
, Users.LastName + ', ' + Users.FirstName + ' - Council: ' + CAST(Groups.CouncilNumber AS VARCHAR) + ', ' + UnitTypes.Name + ' ' + CAST(Groups.UnitNumber AS VARCHAR) AS Text
FROM dbo.AspNetUsers AS Users
JOIN dbo.Groups ON Users.GroupId = dbo.Groups.GroupId
JOIN dbo.UnitTypes ON dbo.Groups.UnitTypeId = dbo.UnitTypes.UnitTypeId
Order by Users.LastName, Users.FirstName ";
var kk = _dbContext.Database.SqlQuery<string>(sql);
SelectList mySl = new SelectList(kk, "Value", "Text");
return mySl;
}
}
}
@model WOA.ViewModels.CustomerViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CustomerViewModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.CustomerId)
<div class="form-group">
@Html.LabelFor(model => model.UserId, "UserId", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.UserId, ViewData.Model.UserSelectList, "Select One", new { @class = "form-control" })
@*@Html.DropDownListFor(model => model.UserId, new SelectList(Model.UserSelectList, "Value", "Text"), htmlAttributes: new { @class = "form-control", id = "UserId" })*@
@Html.ValidationMessageFor(model => model.UserId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
异常消息很明显:来自 EF return 的 SQL 数据 reader(SqlQuery
方法)超过单个值(即 Users.Id
和来自多列的连接字符串)。
此查询 returns Value
& Text
结果集中的列别名,而 SqlQuery
的 return 类型应该是单个 string
:
var sql = @"SELECT Users.Id as Value,
Users.LastName + ', ' + Users.FirstName + ' - Council: ' + CAST(Groups.CouncilNumber AS VARCHAR) + ', ' + UnitTypes.Name + ' ' + CAST(Groups.UnitNumber AS VARCHAR) AS Text
FROM dbo.AspNetUsers AS Users
JOIN dbo.Groups ON Users.GroupId = dbo.Groups.GroupId
JOIN dbo.UnitTypes ON dbo.Groups.UnitTypeId = dbo.UnitTypes.UnitTypeId
Order by Users.LastName, Users.FirstName ";
要解决此问题,请尝试创建额外的 class,其中包含 2 个对应于文本和值属性的属性,例如 SelectListItem
具有:
public class QueryResults
{
public string Value { get; set; } // change to int if Users.Id has integer value
public string Text { get; set; }
}
然后,将查询结果绑定到指定的视图模型中,然后创建List<SelectListItem>
:
var kk = _dbContext.Database.SqlQuery<QueryResults>(sql).ToList();
SelectList mySl = new SelectList(kk, "Value", "Text");
可以找到类似的问题