将Linq查询转换为数据库视图

时间:2015-12-22 10:14:57

标签: c# entity-framework linq sql-server-2008 view

我的数据库中有一个表TestPack,此表与表1-NDocumentationInternalWalk的关系。下面的代码通过从数据库中提取所有测试包并迭代每个测试包来编译测试包状态报告。我的应用程序的架构是数据库托管在Windows服务器计算机(SQL Server)上,客户端应用程序通过网络运行。因此,下面的代码首先获取所有TestPack的列表,并在每次循环迭代中再次查询DocumentationInternalWalk表。这会减慢很多事情。

var AllTestPacks = Project.GetAllTestPacksFromDB();
foreach (var tp in AllTestPacks)
{
    var testPack = new TestPackStatus { TestPackNo = tp.test_pack_no };
    var documentation = tp.Documentations.LastOrDefault();
    if (documentation != null && documentation.status == "Accepted" && documentation.acceptance_date >= cutOffDate)
        testPack.Documentation = documentation.ReadinessDate;
    var internalWalk = tp.InternalWalks.LastOrDefault();
    if (internalWalk != null && internalWalk.status == "Accepted" && internalWalk.acceptance_date >= cutOffDate)
        testPack.InterWalks = internalWalk.AcceptanceDate;
   StatusData.Add(testPack);
}

我在想是否可以将下面的代码翻译成数据库View而我只是从View获取数据,这会显着加快速度。如何将上述代码翻译成View

这是我到目前为止所尝试的内容,但我无法实现此LastOrDefault()

SELECT dbo.TestPack.test_pack_no, dbo.Documentation.rfi_no, dbo.Documentation.rfi_date, dbo.Documentation.status, 
FROM dbo.TestPack INNER JOIN dbo.Documentation ON dbo.TestPack.id = dbo.Documentation.test_pack_id WHERE (dbo.Documentation.status = 'Accepted')

1 个答案:

答案 0 :(得分:0)

假设您希望按Documentation加入“最新”InternalWalktest_pack_no记录并按acceptance_date排序以区分最新记录,则以下SQL(不包括表变量并替换为您自己的表)可以放入传递@cutoff作为参数的存储过程中:

declare @TestPack table (test_pack_no int)
insert into @TestPack values (1)
insert into @TestPack values (2)

declare @Documentation table (test_pack_no int, Name varchar(20), status varchar(20), acceptance_date datetime)
insert into @Documentation values (1, 'Doc 1', 'Accepted', '21 Dec 2015')
insert into @Documentation values (1, 'Doc 2', 'Accepted', '22 Dec 2015')
insert into @Documentation values (2, 'Doc 1', 'Non-Accepted', '22 Dec 2015')
insert into @Documentation values (2, 'Doc 2', 'Accepted', '21 Dec 2015')

declare @InternalWalk table (test_pack_no int, Name varchar(20), status varchar(20), acceptance_date datetime)
insert into @InternalWalk values (1, 'Walk 1', 'Accepted', '20 Dec 2015')
insert into @InternalWalk values (1, 'Walk 2', 'Accepted', '21 Dec 2015')

declare @cutoff datetime = '21 dec 2015'

;with cte_Documentation
as
(
    select
        row_number() over (partition by test_pack_no order by acceptance_date desc) [RN], *
    from
        @Documentation
    where
        status='Accepted'
        and acceptance_date >= @cutoff
),
cte_InternalWalk
as
(
    select
        row_number() over (partition by test_pack_no order by acceptance_date desc) [RN], *
    from
        @InternalWalk
    where
        status='Accepted'
        and acceptance_date >= @cutoff
),
    cte_TestPack
    as
    (
        select
            tp.*, d.status, d.Name [Doc_Name],     d.acceptance_date     [Doc_AcceptDate], iw.Name [InternalWalk_Name], iw.acceptance_date     [InternalkWalk_AcceptDate]
        from
            @TestPack tp
            left join cte_Documentation d on d.test_pack_no=tp.test_pack_no     and d.RN=1
        left join cte_InternalWalk iw on     iw.test_pack_no=tp.test_pack_no and iw.RN=1
)
select * from cte_TestPack

从您的示例中确切地了解哪些列已过滤并且需要作为结果的一部分。

您只需让EF调用SPROC将截止日期作为参数返回,该参数将返回一个平面结构,然后可以将其转换为您的单个对象TestPackDocumentation和{{1 }}