繁体   English   中英

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

[英]Write this SQL query to Entity Framework lambda expression or other way

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

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

因此,您具有带有“ Enquiries和“ FollowUps表。 每个Enquiry都具有零个或多个FollowUps ,每个FollowUp使用一个外键完全属于一个“查询”:一个直接的一对多关系。

如果您遵循实体框架代码优先约定,那么您将拥有类似以下的类:

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

在我看来,FollowUp [20]是FollowUp 1的下一个FollowUp。 如果我更改随访日期[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的任何属性,但其主键除外。 在决定介绍“下一次跟进”的上下文之前,您应该自己考虑一下它是什么:下一次更新吗? 然后,您不需要外键,可以按日期时间排序

暂无
暂无

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

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