带有UserId的MVC Core SelectList和Join到另一个表

时间:2018-01-15 03:03:44

标签: c# asp.net-mvc linq-to-entities asp.net-identity html.dropdownlistfor

我搜索了大量的答案,并尝试了大量的方法来编写代码。目前我正在

  

System.Data.Entity.Core.EntityCommandExecutionException:'数据阅读器有多个字段。多个字段对EDM原语或枚举类型无效。'

在我的部分视图中。

我想学习这一点,所以我花了最后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分配给客户记录。需要显示,以便用户有足够的信息来选择正确的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>

1 个答案:

答案 0 :(得分:0)

异常消息很明显:来自EF的SQL数据读取器(SqlQuery方法)返回的值不止一个(即Users.Id和来自多列的串联字符串)。

此查询返回Value&amp;结果集中的Text列别名,而返回类型SqlQuery应该是单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 ";

要解决此问题,请尝试使用2个属性创建额外的类,这些属性对应于SelectListItem所具有的文本和值属性:

public class QueryResults
{
    public string Value { get; set; } // change to int if Users.Id has integer value
    public string Text { get; set; }
}

然后,将查询结果绑定到指定的viewmodel中,然后创建List<SelectListItem>

var kk = _dbContext.Database.SqlQuery<QueryResults>(sql).ToList();

SelectList mySl = new SelectList(kk, "Value", "Text");

可以找到类似的问题here