【问题标题】:How to turn a DbSet into a dropdown list, for example?例如,如何将 DbSet 变成下拉列表?
【发布时间】:2012-09-28 20:37:44
【问题描述】:

我正试图围绕所有这些 ViewModel 的东西,并以正确的方式做事。我有几个模型通过实体框架链接到 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 中创建一个下拉列表。从技术上讲,我希望每个SelectItem 都说出几列值的字符串组合,但现在我只想要一个,比如配置。这样做的正确方法是什么?我不知道如何操作DbSet。当我尝试从DbSet 中创建Html.DropDownList 时,我得到了一个包含正确数量项目的列表,但它们都说“mynamespace.Models.HardwareOption”。这是有道理的,我只是不知道如何正确地做到这一点。

【问题讨论】:

  • 您的问题的标题非常不具体。请用特定问题替换它:)
  • 这是一个关于 DB 设计的问题还是关于 DBSet 有用的问题。

标签: c# asp.net .net asp.net-mvc entity-framework


【解决方案1】:

在您的示例中使用DbSet&lt;T&gt; 可以做的有用的事情是投影。您将定义第二个 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>

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

public class OrderIndexViewModel
{
    //...

    public int CurrentHardwareOptionId { get; set; }
}

【讨论】:

  • 次要补充:不要忘记覆盖视图模型的 ToString 方法,或者不要直接显示 HardwareOptionViewModel 对象,否则您仍然会得到一个仅包含 "(命名空间).HardwareOptionViewModel" 条目。
  • 感谢您的回复。我几乎需要 HardwareOptions 的所有属性,所以那不是多余的吗?您能否提供一个调用Html.DropDownListHtml.DropDownListFor 的示例? SelectList 是否必须由 IEnumerable&lt;T&gt; 制成,或者我可以用 DbSet&lt;T&gt; 做些什么?再次感谢。
  • @hvd:谢谢!这是我困惑的很大一部分。
  • @Andrew:请参阅我上面关于下拉示例的编辑。如果您需要 all 属性,直接使用 DbSet&lt;T&gt; 可能也可以。仅让视图渲染执行查询而不是控制器(ToList())或存储库或服务或其他东西被认为不是最佳实践。
猜你喜欢
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 2016-05-06
  • 2013-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多