【问题标题】:Using LINQ to "transform" two models on a single View Model使用 LINQ 在单个视图模型上“转换”两个模型
【发布时间】:2017-05-17 18:21:34
【问题描述】:

我正在 ASP.NET 上创建一个页面,并希望将一些模型 (EF) 传递给视图。 该视图包含来自两个不同模型的信息,因此,我为此创建了一个 ViewModel。

首先,我的两个模型:

public class Database
{
  public int Id { get; set; }
  public string Name { get; set; }
  public string Host { get; set; }
  public string Schema { get; set; }
  public ICollection<Group> Groups { get; set; }
}

public class Group
{
  public int Id { get; set; }
  public string Name { get; set; }
  public ICollection<Database> Databases { get; set; }
}

所以,看看我的模型,我有一个Database,它有一个或多个Group,而Group 有一个或多个Database,所以,这是一个多对多的关系。

我的视图显示了一个包含来自Database 模型的所有字段的表单,以及一个包含所有Group 的复选框列表,如果此Group 属于Database,则选中该复选框。

所以,我创建了以下视图模型(欢迎提出建议):

public class DatabaseViewModel
{
  public Database Database { get; set; }
  public List<DatabaseGroupViewModel> Groups { get; set; }
}

public class DatabaseGroupViewModel
{
  public Group Group { get; set; }
  public bool Selected { get; set; }
}

我“直接”使用了DatabaseGroup,因为这是一个 CRUD 表单,并且验证已经在模型上(数据注释)。这里的想法是获取Database,以及所有Group,如果这个Group属于Database,那么Selected属性必须是true

到目前为止一切顺利。

我使用以下代码列出所有Group,如果Group属于Database,则将Selected属性设置为true

int databaseId = 1; // just for example
DatabaseViewModel model = new DatabaseViewModel
{
  Database = await Context.Databases.FirstOrDefaultAsync(d => d.Id == databaseId),
  Groups = Context.Groups.Include(d => d.Databases).OrderBy(g => g.Name).Select(g => new DatabaseGroupViewModel
  {
    Group = g,
    Selected = g.Databases.Any(d => d.Id == databaseId)
  }).ToList()
};

这似乎有效,但我不知道是否是最好的方法。

有什么帮助吗?

编辑:现在可以工作的代码

【问题讨论】:

  • 请不要像您在此处所做的那样以更改问题的方式编辑您的问题。您最初的问题涉及无效的代码并且您想尝试开始工作。您的新问题完全改变了实现,并提出了与您最初提出的问题完全不同的问题。
  • 对不起,但我的问题不是我的代码不能正常工作,而是这种方法是否正确,如果不正确,如何让事情变得更“干净”。
  • 您最初的问题关于您的“无效代码”的。这就是我的观点。您现在有一个新问题,这与您最初在此处发布的问题完全不同。如果您对此有任何疑问,请参阅revisions
  • "cleaner"... 只需将 Context.Database.Include(d=&gt;d.Groups).First(d=&gt;d.Id==databaseId) 作为您的视图模型 (Models.Database) 传递,然后将可能的组放入 Viewbag。

标签: c# .net entity-framework linq


【解决方案1】:

EF 将您的 linq 表达式转置为 SQL 以查询数据库,但并非所有内容都可以表示为 SQL——“LINQ to Entities 无法识别该方法……”是您使用 EF 无法转置的内容时遇到的错误到您的查询中的 SQL。

如果您首先使用 .ToList() 加载值,则不会出现此错误,因为表达式将在内存中进行计算。请注意,这会将数据从数据库拉入内存,因此在使用 ToList() 调用实现实体之前,应尽可能限制使用 EF 支持的表达式选择的数据。

但是,在这种情况下,它是在 linq 表达式中使用 Context.Databases,我认为您可以通过使用已经进入 Select 参数的 Group 参数来完全避免这种情况:

int databaseId = 1; // just for example
DatabaseViewModel model = new DatabaseViewModel
{
  Database = await Context.Databases.FirstOrDefaultAsync(d => d.Id == databaseId),
  Groups = Context.Groups.OrderBy(g => g.Name).Select(g => new DatabaseGroupViewModel
  {
    Group = g,
    Selected =  g.Databases .Any(db => db.Id == databaseId)
  }).ToList()
};

【讨论】:

  • 我必须包含Context.Groups.Include(g =&gt; g.Databases)(延迟加载)
  • @RobertoCorreia .Include 用于预加载,而不是延迟加载。如果您不执行 .Include,则会发生延迟加载。无论如何,它可能会被预先加载,因为它会确定在任何一种情况下它都需要 Selected 属性的数据库 ID,只是一个 FYI。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-01
  • 2010-10-15
  • 2012-02-14
  • 2021-01-29
  • 2020-08-06
  • 1970-01-01
相关资源
最近更新 更多