简体   繁体   English

如何执行两个集合的联接并填充导航属性

[英]How to perform a join of two sets and populate navigation properties

Let's say I have two classes, Teapot and Cup : 假设我有两个课, TeapotCup

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; }
}

and

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; }
}

This is my ViewModel: 这是我的ViewModel:

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

For my ViewModel , I need to perform a join on MaterialId and ColorId and to have some navigation propeties like Teapot.Material.Manufacturer included. 对于我的ViewModel ,我需要对MaterialId和ColorId执行联接,并包含一些导航属性,例如Teapot.Material.Manufacturer So, I've tried following queries: 因此,我尝试了以下查询:

  1. This throws "LINQ to Entities only supports casting EDM primitive or enumeration types" 这将引发“ 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. This seems to ignore the Include 这似乎忽略了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(); 

Now I found some answers here that suggest to enumerate and then to perform another select, but I'd rather catch the data in one go. 现在,我在这里找到了一些答案,建议先进行枚举,然后再执行另一个选择,但我宁愿一口气捕获数据。

You're having difficulties including navigation properties because queries with joins or projections ignore eager loading (see this ). 您遇到的困难包括导航性能,因为与连接的查询或预测忽略预先加载(见 )。

Unfortunately, you will need to do what you seem to be avoiding: pull the data from the database first, then do an additional select to build your ViewModel (which will have the relationships loaded from the original query). 不幸的是,您将需要做的事情似乎是避免的:首先从数据库中提取数据,然后再进行其他选择以构建ViewModel(它将从原始查询中加载关系)。 The additional select should be a rather trivial operation, though, since you're not performing an additional load from the database, and the enumerable should only contain a single item. 但是,由于没有从数据库中执行额外的加载,因此,附加选择应该是相当琐碎的操作,可枚举应仅包含一个项目。

(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();

Source 资源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM