简体   繁体   English

具有许多表,左外部联接和where子句的LINQ查询

[英]LINQ query with many tables, left outer joins, and where clause

I need to translate this SQL query into LINQ in c#. 我需要将此SQL查询转换为c#中的LINQ。 I would appreciate any help or guidance you can give. 我会很感激您能提供的任何帮助或指导。 (I'm using entity framework 6). (我正在使用实体框架6)。

SELECT f.FacId
  ,sli.SitLocIntId
  ,ei.EnvIntId
  ,p.PhoId
FROM Fac AS f
join SitLocInt AS sli on f.FacId = sli.FacId
join EnvInt AS ei on sli.EnvIntId = ei.EnvIntId
join EnvIntTyp AS eit on ei.EnvIntTypId = eit.EnvIntTypId
left outer join Aff AS a on ei.EnvIntId = a.EnvIntId
left outer join AffCon AS ac on a.AffId = ac.AffId
left outer join Con AS c on ac.ConId = c.ConId
left outer join Pho AS p on c.ConId = p.ConId
WHERE EnvIntTyp = 'Fleet'

I've been looking at group join syntax, but with so many tables, a lot of left outer joins and a where clause I haven't made much headway. 我一直在研究组联接语法,但是有这么多的表,很多左外部联接以及where子句,我并没有取得太大进展。 So far I have 到目前为止,我有

    var testQuery =
        from f in _CEMDbContext.setFac
        join sli in _CEMDbContext.setSitLocInt on f.FacId equals sli.FacId
        join ei in _CEMDbContext.setEnvInt on sli.EnvIntId equals ei.EnvIntId
        join eit in _CEMDbContext.setEnvIntTyp on ei.EnvIntTypId equals eit.EnvIntTypId into eiGroup
        from item in eiGroup.DefaultIfEmpty().Where(e => e.EnvIntTyp == "Fleet")
        select new BusinessParticipant
        {
            fac = f,
            sitLocInt = sli,
            envInt = ei,
            // pho = p, // not working... Phone number from table Pho.
        }; 
    var TestList = testQuery.ToList();

Getting the EnvIntTyp "Fleet" and all its associated data including Fac, SitLocInt, and EnvInt is working. 正在获取EnvIntTyp“ Fleet”及其所​​有相关数据,包括Fac,SitLocInt和EnvInt。 But I run into trouble when I try to get the phone number from table Pho which may or may not exist. 但是,当我尝试从表Pho中获取可能不存在的电话号码时,我遇到了麻烦。 Is there a nice way to chain together all the left outer joins? 有没有一种很好的方法可以将所有左外部联接链接在一起? Thanks for advice or direction! 感谢您的建议或指导!

Edit I don't just need the Ids as I wrote in the SQL query, but the whole object. 编辑我不仅需要SQL查询中编写的ID,还需要整个对象。 Plus, I should mention that EnvIntTyp is a member of the table of the same name. 另外,我应该提到EnvIntTyp是同名表的成员。

Edit 2 Here are (parts of) the relevant entities. 编辑2这是相关实体(的一部分)。 Fac is an abbreviation for Facility. Fac是Facility的缩写。 SitLocInt is an abbreviation for SiteLocationInterest. SitLocInt是SiteLocationInterest的缩写。 EnvInt stands for EnvironmentalInterest. EnvInt代表EnvironmentalInterest。 Aff is for Affiliation. Aff是隶属关系。 Con is for Contact. 骗局是为了联系。 Pho is for Phone. Pho用于电话。

public partial class Facility
{
    public Facility()
    {
        this.SiteLocationInterests = new List<SiteLocationInterest>();
    }

    public int FacilityId { get; set; }
    public string FacilityIdentifier { get; set; }
    public string FacilityName { get; set; }
    public int SiteTypeId { get; set; }
    public string FacilityDescription { get; set; }
    [ForeignKey("GeographicFeature")]
    public Nullable<int> GeographicFeatureId { get; set; }
    [Display(Name = "resAddress", ResourceType = typeof(CEMResource))]
    public string AddressLine1 { get; set; }
    [Display(Name = "resAddressLine2", ResourceType = typeof(CEMResource))]
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    [Display(Name = "resState", ResourceType = typeof(CEMResource))]
    public string StateCode { get; set; }
    [Display(Name = "resZip", ResourceType = typeof(CEMResource))]
    public string AddressPostalCode { get; set; }
    public string CountyName { get; set; }
    public virtual GeographicFeature GeographicFeature { get; set; }
    public virtual ICollection<SiteLocationInterest> SiteLocationInterests { get; set; }
}

public partial class SiteLocationInterest
{
    public int SiteLocationInterestId { get; set; }
    [ForeignKey("Facility")]
    public Nullable<int> FacilityId { get; set; }
    [ForeignKey("EnvironmentalInterest")]
    public Nullable<int> EnvironmentalInterestId { get; set; }
    public Nullable<int> EventId { get; set; }
    [ForeignKey("GeographicFeature")]
    public Nullable<int> GeographicFeatureId { get; set; }
    public System.DateTime CreateDate { get; set; }
    public string CreateBy { get; set; }
    public System.DateTime LastUpdateDate { get; set; }
    public string LastUpdateBy { get; set; }
    public virtual EnvironmentalInterest EnvironmentalInterest { get; set; }
    public virtual Facility Facility { get; set; }
    public virtual GeographicFeature GeographicFeature { get; set; }
}

public partial class EnvironmentalInterest
{
    public EnvironmentalInterest()
    {
        this.Affiliations = new List<Affiliation>();
        this.SiteLocationInterests = new List<SiteLocationInterest>();
    }

    public int EnvironmentalInterestId { get; set; }
    public string EnvironmentalInterestIdentifier { get; set; }
    public string EnvironmentalInterestFacilityIdentifier { get; set; }
    public string FacilityIdentifier { get; set; }
    public string EnvironmentalInterestName { get; set; }
    [ForeignKey("EnvironmentalInterestType")]
    public int EnvironmentalInterestTypeId { get; set; }
    public Nullable<int> EnvironmentalInterestSubTypeId { get; set; }
    public string EnvironmentalInterestDescription { get; set; }
    public virtual ICollection<Affiliation> Affiliations { get; set; }
    public virtual EnvironmentalInterestType EnvironmentalInterestType { get; set; }
    public virtual ICollection<SiteLocationInterest> SiteLocationInterests { get; set; }
}

public partial class Affiliation
{
    public Affiliation()
    {
        this.AffiliationContacts = new List<AffiliationContact>();
    }

    public int AffiliationId { get; set; }
    public string AffiliationIdentifier { get; set; }
    public string AffiliationName { get; set; }
    [ForeignKey("Entity")]
    public Nullable<int> EntityId { get; set; }
    [ForeignKey("EnvironmentalInterest")]
    public Nullable<int> EnvironmentalInterestId { get; set; }
    public int AffiliationTypeId { get; set; }
    public int StatusTypeId { get; set; }
    public virtual EnvironmentalInterest EnvironmentalInterest { get; set; }
    public virtual ICollection<AffiliationContact> AffiliationContacts { get; set; }
}

public partial class AffiliationContact
{
    public int AffiliationContactId { get; set; }
    public int AffiliationId { get; set; }
    public int ContactId { get; set; }
    public virtual Affiliation Affiliation { get; set; }
    public virtual Contact Contact { get; set; }
}

public partial class Contact
{
    public Contact()
    {
        this.AffiliationContacts = new List<AffiliationContact>();
        this.Phones = new List<Phone>();
    }

    public int ContactId { get; set; }
    public string ContactIdentifier { get; set; }
    public int EntityId { get; set; }
    public Nullable<int> MailAddressId { get; set; }
    public int ContactTypeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }
    public virtual ICollection<AffiliationContact> AffiliationContacts { get; set; }
    public virtual Entity Entity { get; set; }
    public virtual ICollection<Phone> Phones { get; set; }
}

public partial class Phone
{
    public int PhoneId { get; set; }
    public int ContactId { get; set; }
    public int ContactTypeId { get; set; }
    public string PhoneNumber { get; set; }
    public string PhoneExtensionNumber { get; set; }
    public virtual Contact Contact { get; set; }
    public virtual ContactType ContactType { get; set; }
}
Northwnd db = new Northwnd(@"c:\northwnd.mdf");
IEnumerable<Customer> results = db.ExecuteQuery<Customer>
(@"SELECT c1.custid as CustomerID, c2.custName as ContactName
    FROM customer1 as c1, customer2 as c2
    WHERE c1.custid = c2.custid"
);

As long as the column names in the tabular results match column properties of your entity class, LINQ to SQL creates your objects out of any SQL query. 只要表格结果中的列名与您的实体类的列属性匹配,LINQ to SQL就会从任何SQL查询中创建您的对象。

You're able to execute native SQL code in C# via Linq so you actually don't have to convert this at all. 您可以通过Linq在C#中执行本机SQL代码,因此实际上根本不必进行转换。 Check out this MSDN article: https://msdn.microsoft.com/en-us/library/bb399403(v=vs.110).aspx 查看此MSDN文章: https : //msdn.microsoft.com/zh-cn/library/bb399403(v=vs.110).aspx

Lets reduce the problem into something easier to understand. 让我们将问题简化为更容易理解的东西。 Here's a simple left join: 这是一个简单的左联接:

SELECT As.AId, Bs.BId
FROM As
LEFT JOIN Bs ON As.AId = Bs.AId

And in LINQ: 在LINQ中:

from a in ctx.As
join b in ctx.Bs on a.AId equals b.AId into bgrp // group join -- put matching Bs
                                                 // into a group "bgrp".
from b in bgrp.DefaultIfEmpty()                  // from DefaultIfEmpty() -- if the group
                                                 // has any rows, return them. otherwise,
                                                 // return a single row with the
                                                 // entity's default value (null).
select new
{
    a.AId,
    b.BId
}

You can chain multiple left joins by just repeating: 您只需重复以下操作即可链接多个左联接:

from a in ctx.As
join b in ctx.Bs on a.AId equals b.AId into bs
from b in bs.DefaultIfEmpty()
join c in ctx.Cs on b.BId equals c.BId into cs
from c in cs.DefaultIfEmpty()
select new
{
    a.AId,
    b.BId,
    c.CId
}

Here's how I did it: 这是我的操作方式:

var bpQuery =
    from f in _CEMDbContext.setFac
    join sli in _CEMDbContext.setSitLocInt on f.FacId equals sli.FacId
    join ei in _CEMDbContext.setEnvInt on sli.EnvIntId equals ei.EnvIntId into eiGroup
    from eig in eiGroup.DefaultIfEmpty().Where(e => e.EnvIntTyp.EnvIntTyp == "Fleet")
    join a in _CEMDbContext.setAff on eig.EnvIntId equals a.EnvIntId into aGroup
    from ag in aGroup.DefaultIfEmpty()
    join ac in _CEMDbContext.setAffCon.DefaultIfEmpty() on ag.AffId equals ac.AffId into acGroup
    from acg in acGroup.DefaultIfEmpty()
    join c in _CEMDbContext.setCon.DefaultIfEmpty() on acg.ConId equals c.ConId into cGroup
    from cg in cGroup.DefaultIfEmpty()
    join p in _CEMDbContext.setPho.DefaultIfEmpty() on cg.ContactId equals p.ConId into pGroup
    from pg in pGroup.DefaultIfEmpty()
    select new BusinessParticipant
    {
        facility = f,
        sitLocInt = sli,
        envInt = eig,
        pho = pg,
    };                        

    BusinessParticipantList = bpQuery.ToList();

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

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