将此SQL查询写入Entity Framework lambda表达式或其他方式

问题描述 投票:0回答:1

db.DbEnquiryModules - 如何将此查询写为lambda表达式或linq?

SELECT  
    tenq.EnquiryID
    ,tenq.EnquiryNo
    ,tenq.CompanyID
    ,tenq.EnquiryDate
    ,tenq.ClientID
    ,tenq.Address
    ,tenq.ContactPerson
    ,tenq.Email
    ,tenq.Mobile
    ,tenq.Landline
    ,tenq.SourceID
    ,tenq.PriorityID
    ,tenq.AreaID
    ,tenq.status
    ,tenq.Remark
    ,tenq.IsDeleted
    ,tenq.CreatedDate
    ,tenq.CreatedBy
    ,tenq.ModifiedDate
    ,tenq.ModifiedBy
    ,Y.FollowupDate AS LastFollowup
    ,Y.NextFollowup AS NextFollowup
    ,srno2
INTO
    #tmp 
FROM
    tblEnquiryModule tenq
LEFT JOIN 
   (SELECT 
        ROW_NUMBER() OVER (PARTITION BY EnquiryModuleID ORDER BY FollowupId DESC) SRno2,
        * 
    FROM
        tblFollowup) Y ON Y.EnquiryModuleID = EnquiryID
                       AND Y.srno2 <=2  ----------Last followUp
WHERE
    tenq.CompanyID = @companyid


--

DELETE a
FROM #tmp a
JOIN #tmp b ON a.EnquiryID = b.EnquiryID
            AND b.srno2 = 2
WHERE a.srno2 = 1 

SELECT * FROM #tmp 

我有两个查询表及其followup.above查询返回查询及其最后一个后续日期(如果存在)和下一个后续日期

我的实体

public class DTOEnquiryModule
{   [Key]
    public int EnquiryID { get; set; }
    public string EnquiryNo { get; set; }
    public int CompanyID { get; set; }
    public DateTime? EnquiryDate { get; set; }
    public string Mobile { get; set; }
    public string Landline { get; set; }
    public string status { get; set; }
    public int? ModifiedBy { get; set; }}  

public class DTOFollowup
{
    [Key]
    public int FollowupId { get; set; }
    public int EnquiryModuleID { get; set; }
    [ForeignKey("EnquiryModuleID")]
    public DTOEnquiryModule EnquiryModule { get; set; }
    public DateTime FollowupDate { get; set; }
    public string FollowupRemark { get; set; }
    public DateTime? NextFollowup { get; set; }
    public string NextFollowupRemark { get; set; }
}

咨询表

|EnquiryID|EnquiryNo|EnquiryDate            |status 
|1        |EN1      |2019-02-19 00:00:00.000|ongoing
|2        |EN2      |2019-02-20 00:00:00.000|ongoing
|3        |EN3      |2019-02-23 00:00:00.000|ongoing

跟进表

FollowupId|EnquiryModuleID|FollowupDate           |FollowupRemark|NextFollowup 
1         |1              |2019-02-20 00:00:00.000|NA            |NULL
2         |2              |2019-02-21 00:00:00.000|NA            |2019-02-23 00:00:00.000
3         |2              |2019-02-23 00:00:00.000|NA            |NULL
4         |3              |2019-02-24 00:00:00.000|NA            |2019-02-26 00:00:00.000
5         |3              |2019-02-26 00:00:00.000|NA            |2019-02-28 00:00:00.000
6         |3              |2019-02-28 00:00:00.000|NA            |NULL

我想要下面的结果表

|EnquiryID|EnquiryNo|EnquiryDate            |status |NextFollowup           |LastFollowup
|1        |EN1      |2019-02-19 00:00:00.000|ongoing|NULL                   |2019-02-20 00:00:00.000
|2        |EN2      |2019-02-20 00:00:00.000|ongoing|2019-02-23 00:00:00.000|2019-02-21 00:00:00.000
|3        |EN3      |2019-02-23 00:00:00.000|ongoing|2019-02-28 00:00:00.000|2019-02-26 00:00:00.000

当我添加新的后续内容时,需要更新以前的维护历史记录的后续详细信息,并通过查询ID获取最新的后续跟进。

我想在最后一次跟进和下一个跟进日期显示查询列表

c# entity-framework linq linq-to-sql entity-framework-6
1个回答
0
投票

所以你有EnquiriesFollowUps的桌子。每个Enquiry都有零个或多个FollowUps,每个FollowUp都属于一个`查询,使用外键:一个简单的一对多关系。

如果你跟着entity framework code first conventions,你会有类似的课程:

class Enquiry
{
    public int Id {get; set; }
    public string EnquiryNo { get; set; }
    public DateTime? EnquiryDate { get; set; }
    public string status { get; set; }
    ...

    // every Enquiry has zero or more FollowUps (one-to-many)
    public virtual ICollection<FollowUp> FollowUps {get; set;}
}

class FollowUp
{
    public int Id {get; set; }
    public DateTime FollowupDate { get; set; }
    ...

    // every FollowUp belongs to exactly one Enquiry, using foreign key
    public int EnquiryId {get; set;}
    public virtual Enquiry Enquiry {get; set;}
}

为了完整性,DbContext:

class MyDbContext : DbContext
{
    public DbSet<Enquiry> Enquiries {get; set;}
    public DbSet<FollowUp> FollowUps {get; set;}
}

因为我遵循了约定,这就是实体框架需要知道的所有内容,以检测表,表中的列以及表之间的关系。只有当您需要不同的标识符时,您才需要属性或流畅的API。这一点的重要部分是我通过使用虚拟属性指定一对多

在实体框架中,列由非虚拟属性表示;虚拟属性表示表之间的关系(一对多,多对多,......)

您的要求:“当我添加新的后续操作时,需要更新以前的后续详细信息”。

我加了?需要更新以前的跟进?也许你应该研究你的需求技巧。

我想你的意思如下:

要求给我(一些属性)所有查询,其最新的FollowUpDate及其最新但一个FollowupDate(由于某种原因你决定调用最后一个日期)。

如果查询只有一个后续,我想要EnquiryDate和Follow Update。如果询问没有跟进,我只想要EnquiryDate。

因此,符合条件的FollowUpdates的集合是EnquiryDate +所有FollowUpdates。按降序排列日期,然后选择前两个。

var result = dbContext.Enquiries.Select(enquiry => new
{
    EnquiryId = enquiry.Id,
    EnquiryNo = enquiry.EnquiryNo,
    EnquiryDate = enquiry.EnquiryDate,
    Status = enquiry.Status,

    // For the followups: take the followUp dates as nullable DateTime
    // and add the EnquiryDate
    FollowUps = enquiry.FollowUps
        .Select(followUp => followUp.FollowUpdate)
        .Cast<DateTime?>()
        .Concat(new DateTime?[] {enquiry.EnquiryDate})

        // take the two newest ones; we don't want null values
        .Where(date => date != null)
        .OrderByDescending(date => date)
        .Take(2)
        .ToList(),
})

// move this to local process, so you can use FollowUps to get Next / Last
.AsEnumerable()
.Select(fetchedData => new
{
    EnquiryId = fetchedData.EnquiryId,
    EnquiryNo = fetchedData.EnquiryNo,
    EnquiryDate = fetchedData.EnquiryDate,
    Status = fetchedData.Status,

    // FollowUps are ordered in Descending order. FirstOrDefault is the newest!
    NextFollowUp = enquiry.FollowUps.FirstOrDefault(),
    LastFollowUp = enquiry.FollowUps.LastOrDefault(),
}

实体框架知道您的一对多关系。它会将您对ICollection的使用转换为GroupJoin

如果需要,您可以让数据库管理系统选择NextFollowUp和LastFollowUp。传输的数据数量相同,因此不会加快您的流程。

有些人不喜欢使用virtual ICollection来获取“跟随他们的询问”。你可以自己做GroupJoin:

result = dbContext.Enquiries.GroupJoin(dbContext.FollowUps,
    enquiry => enquiry.Id,           // from each enquiry take the primary key
    followUp => followUp.EnquiryId,  // from each followUp take the foreign key

    // result selection: use each enquiry with all its matching followUps to make a new
    (enquiry, followUpsOfThisEnquiry) => new
    {
        EnquiryId = enquiry.Id,
        ... etc.

保持数据库规范化

您决定在数据库中添加DateTime列NextFollowUp。这不是一个好的选择。

Id | FollowUpDate | NextFollowUpDate
01 |  2019-02-13  |  2019-02-14
20 |  2020-02-29  |     null

在我看来,FollowUp [20]是跟进qazxsw poi的下一个跟进。如果我更改FollowUp [20]的日期会发生什么:

1

这仍然是正确的吗? [20]突然不是[01]的下一个吗?每当您更改日期时,您都必须检查所有FollowUps以查看它是否指向此FollowUp。

以下是什么:

Id | FollowUpDate | NextFollowUpDate
01 |  2019-02-13  |  2019-02-14
20 |  2019-02-14  |     null

谁是[04]的下一个?

请记住,跟进由其主键标识,而不是由其日期标识。跟进日期可能会改变。然而,这并没有改变后续行动本身。

Id | FollowUpDate | NextFollowUpDate
04 |  2019-02-13  |  2019-02-14
05 |  2019-02-14  |     null
06 |  2019-02-14  |     null

介绍之后,您可以安全地更改FollowUp的任何属性,当然除了它的主键。在您决定介绍“下一步跟进”的背景之前,您应该自己思考它是什么:它是下一个日期吗?然后您不需要外键,您可以按日期时间订购它们

© www.soinside.com 2019 - 2024. All rights reserved.