【问题标题】:Linq With Entities List within Distinct ListLinq 与不同列表中的实体列表
【发布时间】:2015-10-21 01:37:06
【问题描述】:

我有一个获取不同行的供应商联系人的 SQL 查询,它返回正确的行数:

SELECT  DISTINCT v.VendorID, c.ContactID, 
    v.VendorName, 
    c.FirstName, c.MiddleName, c.LastName,      
FROM VendorContacts vc
INNER JOIN Contact c
    ON c.ContactID = vc.ContactID
INNER JOIN Vendor v
    ON v.VendorID = vc.VendorID
LEFT JOIN [ContactServices] psvc
    ON psvc.ContactID = c.ContactID
    AND psvc.VendorID = v.VendorID

根据上面的查询,我有一个想要返回自定义类型的方法:

public List<ProviderContactInfo> GetProviderContactInfo(ProviderContactInfo searchInfo)
{
    using (var db = new MyContext()) 
    {
        var providerContactInfo =
              (from vc in db.VendorContacts
               join ps in db.ContactServices on new { vc.ContactID, vc.VendorID } equals new { ps.ContactID, ps.VendorID } into ps_join
               from ps in ps_join.DefaultIfEmpty()
               join c in db.Contacts on vc.ContactID equals c.ContactID
               join v in db.Vendors on vc.VendorID equals v.VendorID                                           
               orderby vc.ContactID descending

               select new ProviderContactInfo()
               {
                VendorName = v.VendorName,
                FirstName = c.FirstName,
                MiddleName = c.MiddleName,
                LastName = c.LastName,
                Services = (from o in db.ContactServices
                            join cps in db.Contacts on o.ContactID equals cps.ContactID
                            join vps in db.Vendors on o.VendorID equals vps.VendorID
                            join s in db.Services on o.ServiceID equals s.ServiceID
                            where ps.ServiceID == o.ServiceID
                            && o.ContactID == c.ContactID
                            && o.VendorID == v.VendorID
                            select s).ToList()
               }).Distinct().ToList();

        return providerContactInfo;
    }
}

我收到了错误:

附加信息:“Distinct”操作不能应用于 指定参数的集合 ResultType。

当我从新的 ProviderContactInfo 中删除 Services 属性时,一切正常,所以我确定这是我尝试填充该属性(类型为 List&lt;Service&gt;)的方式

我知道有很多关于 Linq with Distinct 等的问题,但我找不到关于这个特定问题的任何信息。

请帮忙!

编辑此代码有效:

public List<ProviderContactInfo> GetProviderContactInfo(ProviderContactInfo searchInfo)
    {
        using (var db = new MyContext()) 
        {
            var providerContactInfo =
                  (from vc in db.VendorContacts
                   join c in db.Contacts on vc.ContactID equals c.ContactID
                   join v in db.Vendors on vc.VendorID equals v.VendorID                                           
                   orderby vc.ContactID descending

                   select new ProviderContactInfo()
                   {
                    VendorName = v.VendorName,
                    FirstName = c.FirstName,
                    MiddleName = c.MiddleName,
                    LastName = c.LastName,
                    Services = (from o in db.ContactServices
                                join cps in db.Contacts on o.ContactID equals cps.ContactID
                                join vps in db.Vendors on o.VendorID equals vps.VendorID
                                join s in db.Services on o.ServiceID equals s.ServiceID
                                where o.ContactID == c.ContactID
                                && o.VendorID == v.VendorID
                                select s).ToList()
                   }).Distinct().ToList();

            return providerContactInfo;
        }
    }

【问题讨论】:

  • 如果用 .ToList().Distinct() 而不是 .Distinct().ToList() 结束会发生什么?
  • 错误 CS0266 无法将类型“System.Collections.Generic.IEnumerable”隐式转换为“System.Collections.Generic.List”。存在显式转换(您是否缺少演员表?)
  • 您是否尝试过为 ProviderContactInfo 创建自定义比较器并将其传递给 distinct 函数?参考stackoverflow.com/questions/31681929/…

标签: c# sql linq entity-framework-6


【解决方案1】:

您应该在该过程中再添加一个步骤,以避免在具有集合 (Services) 属性的对象上应用 Distinct(),因为 LINQ 提供程序不知道如何处理它。

var providerContactInfo = from vc in db.VendorContacts
                          join ps in db.ContactServices on new { vc.ContactID, vc.VendorID } equals new { ps.ContactID, ps.VendorID } into ps_join
                          from ps in ps_join.DefaultIfEmpty()
                          join c in db.Contacts on vc.ContactID equals c.ContactID
                          join v in db.Vendors on vc.VendorID equals v.VendorID                                           
                          orderby vc.ContactID descending
                          group ps by new
                          {
                              v.VendorName,
                              c.FirstName,
                              c.MiddleName,
                              c.LastName,
                              c.ContactID,
                              v.VendorID
                          } into g
                          select new ProviderContactInfo()
                          {
                              VendorName = g.Key.VendorName,
                              FirstName = g.Key.FirstName,
                              MiddleName = g.Key.MiddleName,
                              LastName = g.Key.LastName,
                              Services = (from e in g
                                          from o in db.ContactServices
                                          join cps in db.Contacts on o.ContactID equals cps.ContactID
                                          join vps in db.Vendors on o.VendorID equals vps.VendorID
                                          join s in db.Services on o.ServiceID equals s.ServiceID
                                          where e.ServiceID == o.ServiceID
                                          && o.ContactID == g.Key.ContactID
                                          && o.VendorID == g.Key.VendorID
                                          select s).ToList()
                          }

【讨论】:

  • 这是目前看来效果最好的方法,至少填充了 Services 属性并且没有发生错误,但是我的 ProviderContactInfo 行与 SQL 中的 SQL 语句中返回的不同服务器管理工​​作室。
  • 当我运行此代码时,我收到错误 CS0103 The name 'ps' does not exist in the current context。 (指行:其中 ps.ServiceID == o.ServiceID)
  • 加入 ContactServices 导致联系人出现在他提供的许多服务中,因此我没有在服务集合中获得一个具有 8 个服务的联系人,而是得到 8 个相同的联系人,每个联系人具有一项服务.
  • @TrevorBrooks 我更新了解决这个问题的答案。
  • 我们快到了,我希望返回类型为 List,现在它在抱怨:错误 CS0266 无法将类型'System.Linq.IQueryable' 隐式转换为' System.Collections.Generic.List'。存在显式转换(您是否缺少演员表?)
【解决方案2】:

这不是更简单吗:

public IQueryable<VendorContact> GetProviderContactInfo(ProviderContactInfo searchInfo)
{
  using (var db = new MyContext()) 
  {
    return providerContactInfo=db.VendorContacts
      .Include(vc=>vc.Contacts)
      .Include(vc=>vc.Services)
      .Include(vc=>vc.Vendor)
      .OrderByDescending(vc=>vc.ContactID);
  }
}

【讨论】:

  • 这看起来确实简单多了,也许我遗漏了什么,但我得到 CS1660 Cannot convert lambda expression to type 'string' because it is not a delegate type on vc=>vc.Contacts
  • 你需要@using System.Linq
  • Include()的lambda版本需要添加using System.Data.Entity;
  • 仅供参考我得到的错误是:错误 CS1061 'VendorContact' 不包含'Contacts' 的定义,并且找不到接受'VendorContact' 类型的第一个参数的扩展方法'Contacts'(是您缺少 using 指令或程序集引用?)
  • 您在 VendorContact 上设置的导航属性是什么,以引用您的联系人?在 VendorContact.cs 中应该有一个类似的属性:public virtual ICollection&lt;Contact&gt; Contacts { get; set; }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-08
  • 1970-01-01
相关资源
最近更新 更多