【问题标题】:How to perform a join of two sets and populate navigation properties如何执行两个集合的连接并填充导航属性
【发布时间】:2015-05-26 20:53:44
【问题描述】:

假设我有两个班级,Teapot 和 Cup:

public class Teapot
{
    [Key]
    [Column("Id", TypeName = "int")]
    public int Id         { get; set; }

    public int MaterialId { get; set; }

    public int ColorId    { get; set; }

    [ForeignKey("MaterialId")]
    public virtual Material Material { get; set; }
    [ForeignKey("ColorId")]
    public virtual Color    Color    { get; set; }
}

和

public class Cup
{
    [Key]
    [Column("Id", TypeName = "int")]
    public int Id         { get; set; }

    public int MaterialId { get; set; }

    public int ColorId    { get; set; }

    [ForeignKey("MaterialId")]
    public virtual Material Material { get; set; }
    [ForeignKey("ColorId")]
    public virtual Color    Color    { get; set; }
}

这是我的 ViewModel:

namespace ViewModel.Data
{
    public class TeapotsWithInfo
    {
        public Model.Data.Teapot Teapot { get; set; }
        public Model.Data.Cup    Cup    { get; set; }
    }
}

对于我的ViewModel,我需要对 MaterialId 和 ColorId 执行连接,并包含一些导航属性,例如 Teapot.Material.Manufacturer。所以,我尝试了以下查询:

  1. 这会抛出“LINQ to Entities 仅支持转换 EDM 基元或枚举类型”

    (from t in db.Teapots
     join c in db.Cups
     on new { t.MaterialId, t.ColorId } equals new { c.MaterialId, c.ColorId }
     where t.Id == id
     select new ViewModel.Data.TeapotsWithInfo { Teapot = t, Cup = c })
        .Include(t => t.Material.Manufacturer).SingleOrDefault();
    
  2. 这似乎忽略了Include

     (from t in db.Teapots.Include(t => t.Material.Manufacturer)
     join c in db.Cups
     on new { t.MaterialId, t.ColorId } equals new { c.MaterialId, c.ColorId }
     where t.Id == id
     select new ViewModel.Data.TeapotsWithInfo { Teapot = t, Cup = c }).SingleOrDefault();
    

现在我在这里找到了一些建议枚举然后执行另一个选择的答案,但我宁愿一次性捕获数据。

【问题讨论】:

  • “一次”是什么意思?如果你枚举然后选择,你只会发送一个数据库查询。

标签: c# asp.net linq entity-framework linq-to-entities


【解决方案1】:

您在包含导航属性时遇到了困难,因为带有连接或投影的查询会忽略预加载(请参阅this)。

不幸的是,您将需要做您似乎在避免的事情:首先从数据库中提取数据,然后再进行一次选择以构建您的 ViewModel(将从原始查询中加载关系)。不过,额外的选择应该是一个相当简单的操作,因为您没有从数据库执行额外的加载,并且可枚举应该只包含一个项目。

(from t in db.Teapots.Include(t => t.Material.Manufacturer)
 join c in db.Cups
 on new { t.MaterialId, t.ColorId } equals new { c.MaterialId, c.ColorId }
 where t.Id == id
 select new 
  {
     Teapot = t,
     Cup = c,
     Material = t.Material,
     Manufacturer = t.Material.Manufacturer,
  })
.AsEnumerable()
.Select(a => new ViewModel.Data.TeapotsWithInfo 
  { 
     Teapot = a.Teapot, 
     Cup = a.Cup 
  })
.SingleOrDefault();

来源

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多