如何将一个DbSet转换为下拉列表,例如?

3

我试图理解所有这些ViewModel的东西,并且以正确的方式处理事情。我有几个模型通过Entity Framework链接到SQL表,就像这个:

[Table("HardwareOptions", Schema = "dbo")]
public class HardwareOption {
  [Key]
  public int RecordID {get; set;}
  [ForeignKey("Configuration")]
  public string Configuration {get; set;}
  public string ComputerManufacturer {get; set;}
  public string ComputerModel {get; set;}
  public string ComputerDescription {get; set;}
  public int MonitorCount {get; set;}
  public string MonitorManufacturer {get; set;}
  public string MonitorModel {get; set;}
  public string MonitorDescription {get; set;}
}

我有一个像这样的视图模型:

public class OrderIndexViewModel {
  public Customer Customer {get; set;}
  public MetaUser MetaUser {get; set;}
  public DbSet<HardwareOption> HardwareOptions {get; set;}
  public DbSet<Machine> Machines {get; set;}
  public DbSet<PendingOrder> PendingOrders {get; set;}
}

我的控制器代码如下:

private MyDbContext db = new MyDbContext();
OrderIndexViewModel viewmodel = new OrderIndexViewModel();
viewmodel.Customer = db.Customers.Find("myselffortesting");
viewmodel.MetaUser = db.MetaUsers.Find("myselffortesting");
viewmodel.HardwareOptions = db.HardwareOptions;
viewmodel.Machines = db.Machines;
viewmodel.PendingOrders = db.PendingOrders;
return View(viewmodel);

因此,从我的角度来看,我只需要有关一个客户/用户的信息,但我需要能够查询整个HardwareOptions、Machines和PendingOrders表。如果我的架构完全错误,请告诉我,因为这更多是关于这个问题的。但是对于某些特定的事情,比如我想从HardwareOptions中制作一个下拉列表。从技术上讲,我希望每个都说几列值的字符串组合,但现在我只想要一个,比如Configuration。正确的做法是什么?我不知道如何操作。当我试图从制作时,我得到了一个具有正确数量项目的列表,但它们都说“mynamespace.Models.HardwareOption。”这是有道理的,我只是无法弄清楚如何做到这一点。

你的问题标题非常不具体,请用一个具体的问题来替换它 :) - Codeman
这是关于数据库设计还是关于使用DBSets的有用事情的问题。 - Ash Machine
1个回答

6
你可以在例子中使用 DbSet<T> 来进行有用的投影操作。你需要定义一个包含想要在下拉列表中显示的属性的第二个 ViewModel :
public class HardwareOptionViewModel
{
    public int Id { get; set; }
    public string Configuration { get; set; }
    public string AnotherProperty { get; set; }
    //...
}

您可以在OrderIndexViewModel中使用此ViewModel的集合,而不是使用DbSet

public class OrderIndexViewModel
{
    //...
    public IEnumerable<HardwareOptionViewModel> HardwareOptions { get; set; }
    //...
}

仅使用Select方法从数据库加载这些属性:

viewmodel.HardwareOptions = db.HardwareOptions
    .Select(h => new HardwareOptionViewModel
    {
        Id = h.Id,
        Configuration = h.Configuration,
        AnotherProperty = h.AnotherProperty,
        //...
    })
    .ToList();

编辑

您可以将集合绑定到下拉列表中,如下所示:

@model MyNamespace.OrderIndexViewModel

...

<div>
    @Html.DropDownListFor(model => model.CurrentHardwareOptionId,
        new SelectList(Model.HardwareOptions, "Id", "Configuration",
                       Model.CurrentHardwareOptionId))
</div>

我这里介绍了一个新属性CurrentHardwareOptionId,它在OrderIndexViewModel上具有与Id相同的类型(在示例中为int),并且当页面被提交时,所选的下拉列表中的Id应该绑定到这个属性:

public class OrderIndexViewModel
{
    //...

    public int CurrentHardwareOptionId { get; set; }
}

2
小细节:不要忘记重写视图模型的 ToString 方法,或者不要直接显示 HardwareOptionViewModel 对象,否则你仍然会得到一个下拉列表,其中只有 "(namespace).HardwareOptionViewModel" 条目。 - user743382
谢谢您的回复。我需要HardwareOptions的几乎每个属性,那不是有点冗余吗?您能否提供一下调用Html.DropDownListHtml.DropDownListFor的示例?SelectList必须由IEnumerable<T>制作,还是我可以使用DbSet<T>做些什么?再次感谢。 - Andrew
@hvd:谢谢!那是我困惑的重要部分。 - Andrew
1
@Andrew:请看我上面的编辑关于下拉菜单示例的说明。如果您需要所有属性,直接使用DbSet<T>可能也可以工作。让视图渲染执行查询而不是控制器(ToList())或存储库或服务等被认为不是最佳实践。 - Slauma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接