为什么LINQ To SQL会像这样生成SQL?

时间:2011-02-22 12:31:02

标签: c# .net linq-to-sql

当LINQ将以下语法转换为SQL时,(inner)where子句将移动到最外层查询。这对数据库非常不友好。我写的就像Hibernate的HQL(这是合适的吗?),我已经为许多卫星编写了SQL。

任何人都可以帮忙解释一下给出的内容,或者指出我的决议方式吗?

        var rc = (
            from dv in (
                from dv_j in (
                    from x in adc.JobManagement
                    join j in adc.Job on x.JobId equals j.JobId
                    join js in adc.JobStatus on j.StatusId equals js.JobStatusId
                    join cm in adc.ClientManagement on j.ClientId equals cm.ClientId
                    join o in adc.User on cm.UserId equals o.UserId
                    join jm in adc.JobManagement on j.JobId equals jm.JobId
                    where
                        (x.UserId == aid || cm.UserId == aid)
                        && (j.StatusDate == null || j.StatusDate >= getFromDate())
                        && (jm.ManagementRoleCode == MR_MANAGER)
                    select new
                    {
                        j.JobId,
                        Job = j.InternalName == null ? j.ExternalName : j.InternalName,
                        JobStatusDate = j.StatusDate,
                        JobStatus = js.Code,
                        Owner = o.Username,
                        Role = jm.ManagementRoleCode
                    })
                join s in adc.Submission on dv_j.JobId equals s.JobId into dv_s
                from s in dv_s.DefaultIfEmpty()
                select new
                {
                    dv_j.JobId,
                    dv_j.Job,
                    dv_j.JobStatusDate,
                    dv_j.JobStatus,
                    dv_j.Owner,
                    dv_j.Role,
                    s.SubmissionId,
                    s.CandidateId,
                    s.SubmissionDate,
                    StatusDate = s.StatusDate,
                    StatusId = s.StatusId
                })
            join c in adc.Candidate on dv.CandidateId equals c.CandidateId into dv_c
            join ss in adc.SubmissionStatus on dv.StatusId equals ss.SubmissionStatusId into dv_ss
            from c in dv_c.DefaultIfEmpty()
            from ss in dv_ss.DefaultIfEmpty()
            orderby
                dv.StatusId == null ? dv.StatusDate : dv.JobStatusDate descending,
                dv.Job,
                c.LastName,
                c.NickName,
                c.FirstName
            select new Projects
            {
                Id = dv.JobId,
                Project = dv.Job,
                Submitted = dv.SubmissionDate,
                Candidate = FormatIndividual(c.LastName, c.FirstName, c.NickName),
                Status = dv.StatusId == null ? ss.Code : dv.JobStatus,
                StatusDate = dv.StatusId == null ? dv.StatusDate : dv.JobStatusDate,
                Role = dv.Role,
                Owner = dv.Owner
            });

1 个答案:

答案 0 :(得分:0)

尝试将一个语句分解为两个。这可以工作,因为它无法移动到一个尚不存在的地方。这确实可以进行多次往返数据库,但是最好将几个大表连接起来然后剔除。我会试试这个:

var inMemoryTable = (
    from x in adc.JobManagement
    join j in adc.Job on x.JobId equals j.JobId
    join js in adc.JobStatus on j.StatusId equals js.JobStatusId
    join cm in adc.ClientManagement on j.ClientId equals cm.ClientId
    join o in adc.User on cm.UserId equals o.UserId
    join jm in adc.JobManagement on j.JobId equals jm.JobId
    where
        (x.UserId == aid || cm.UserId == aid)
        && (j.StatusDate == null || j.StatusDate >= getFromDate())
        && (jm.ManagementRoleCode == MR_MANAGER)
    select new
    {
        j.JobId,
        Job = j.InternalName == null ? j.ExternalName : j.InternalName,
        JobStatusDate = j.StatusDate,
        JobStatus = js.Code,
        Owner = o.Username,
        Role = jm.ManagementRoleCode
    });

var rc = (
    from dv in (
        from dv_j in inMemoryTable
        join s in adc.Submission on dv_j.JobId equals s.JobId into dv_s
        from s in dv_s.DefaultIfEmpty()
        select new
        {
            dv_j.JobId,
            dv_j.Job,
            dv_j.JobStatusDate,
            dv_j.JobStatus,
            dv_j.Owner,
            dv_j.Role,
            s.SubmissionId,
            s.CandidateId,
            s.SubmissionDate,
            StatusDate = s.StatusDate,
            StatusId = s.StatusId
        })
    join c in adc.Candidate on dv.CandidateId equals c.CandidateId into dv_c
    join ss in adc.SubmissionStatus on dv.StatusId equals ss.SubmissionStatusId into dv_ss
    from c in dv_c.DefaultIfEmpty()
    from ss in dv_ss.DefaultIfEmpty()
    orderby
        dv.StatusId == null ? dv.StatusDate : dv.JobStatusDate descending,
        dv.Job,
        c.LastName,
        c.NickName,
        c.FirstName
    select new Projects
    {
        Id = dv.JobId,
        Project = dv.Job,
        Submitted = dv.SubmissionDate,
        Candidate = FormatIndividual(c.LastName, c.FirstName, c.NickName),
        Status = dv.StatusId == null ? ss.Code : dv.JobStatus,
        StatusDate = dv.StatusId == null ? dv.StatusDate : dv.JobStatusDate,
        Role = dv.Role,
        Owner = dv.Owner
    });