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

时间:2019-02-27 04:22:07

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

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 

我有两个带有查询表和后续查询的表。上面的查询返回查询及其最后的跟踪日期(如果存在)和下一个跟踪日期

我的实体

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获得最新的跟踪记录。

我想显示上次跟进和下一次跟进日期的查询清单

1 个答案:

答案 0 :(得分: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和FollowUpdate。如果查询没有后续行动,我只需要查询日期。

因此,合格的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

在我看来,跟进[20]是跟进1的下一个跟进。如果我更改随访日期[20],该怎么办?

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

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

接下来呢?

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

[04]的下一个是谁?

请记住,后续操作是通过主键而不是日期来标识的。随访日期可能会改变。但这并不会改变后续行动本身。

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

引入后,您可以安全地更改FollowUp的任何属性,当然,其主键除外。在决定介绍“下一次跟进”的上下文之前,您应该自己考虑一下它是什么:下一次更新吗?然后,您不需要外键,可以按日期时间排序