向我推荐一个合适的LINQ提供程序(SQL服务器,复杂查询)

Ron*_*dau 5 linq linq-to-entities sql-server-2008 linq-to-sql c#-4.0

我一直在使用LINQ to SQL和实体一段时间,我对它们总体上非常满意.但是,我知道它们的局限性,特别是对我来说这是一个很大的问题.当您以形式执行复杂的嵌套查询时

MyContext.SomeTable
.Select(item=>new{
    item.SomeProperty1,
    item.SomeProperty2,
    item.NavigationProperty1
        .Select(nav1=> new {// retrieve some properties}), // This triggers a single query as long as don't have more than one subquery
    item.NavigationProperty2
        .Select(nav2=> new {// retrieve some properties}) // This triggers one query PER ROW in the original query
});
Run Code Online (Sandbox Code Playgroud)

我测试过的提供程序是LINQ TO SQL/LINQ TO实体(更糟糕的是,启动LINQConnect,情况更糟,在第一个导航属性上每行生成1个)

我现在得到的是什么(伪代码):

select t1.a,t1.b,t2.c,t2.d from mytable as t1
join navproperty1table as t2
Run Code Online (Sandbox Code Playgroud)

和这样的查询中有1百万(如果第一组中有100万个结果):( select t3.e,t3.f from navproperty2table as t3 where id = XX将X查询更改为第一个查询返回的下一个元素)

我想要的是:

select t1.a,t1.b,t2.c,t2.d,t3.e,t3.f from mytable as t1 
join navproperty1table as t2
join navproperty2table as t3
Run Code Online (Sandbox Code Playgroud)

现在当然如果原始表中有3行就不会出现问题,但是我的表中有数十万到数百万行"和"我需要在单个选择中进行更复杂的查询(我希望立刻得到一个复杂的图表.考虑具有3-6级嵌套的20 +表,每个表访问额外的2-5个表.

我的SQL服务器可以完美地处理它,我也不关心带宽,它是在一个千兆连接链接的实例上,我不能以延迟的方式获取数据,我实际上"立即"使用它所有的这不只是懒惰.现在出于性能原因我不得不在许多小查询中拆分查询并在LINQ上手动连接到对象大小,这给了一些非常讨厌的代码,无论谁维护它但是我唯一的实际解决方案,所以整体包括所有小问题和最终加入,我在一个完全无法维护的单一方法中有600多行不可分割的代码.

实际上是否有"任何"LINQ提供商的产品准备就绪,然后才开始评估所有以这种思维模式工作的方式,或者我最好编码和商业化自己的产品?(我很惊讶他们实际上并不都是这样做的,我看不到一个单独的例子,你对foreach案例和我试过要求摆脱n的情况会更好带有loadwith的+1,不要摆脱它,因为他们仍然进行n + 1个查询但只是在一次调用中批量处理,1次往返&n + 1次查询不满意当1为10 000然后10 000 000然后是10 000 000 000)

  • (请注意,我正在猜测究竟是什么触发了这一点,但这不是问题,无论是什么触发这个"确切"我肯定会在我目前的背景下触及它)

PS:请注意,我在Windows Server 2008或更高版本上运行.NET 4.0完整配置文件,在SQL Server 2008或更高版本上,不支持其他任何内容的提供程序都没问题,我对迁移,可移植性,较低的.net版本,较低的sql server支持等.如果需要,可以选择迁移到更新版本.我也没有任何建模或高级功能的先决条件,数据库已经存在,我只想查询表,所以没有建模/视图/ DML /存储过程/函数支持的东西是好的,我唯一的要求是复杂查询和对象图上合理的SQL生成

编辑:这里的澄清是每个人都可以获得的数据库问题的实际示例,冒险工作

查询每个联系人的员工

Contacts
.Select(cont=>new 
{
    cont.EmailAddress,
    cont.EmailPromotion,
    Employees = cont.Employees
        .Select(emp=>new
        {
            emp.Gender,
            emp.HireDate
        }).ToList()
}).ToList()
Run Code Online (Sandbox Code Playgroud)

生成

SELECT [t0].[EmailAddress], [t0].[EmailPromotion], [t1].[Gender], [t1].[HireDate], (
SELECT COUNT(*)
FROM [HumanResources].[Employee] AS [t2]
WHERE [t2].[ContactID] = [t0].[ContactID]
) AS [value]
Run Code Online (Sandbox Code Playgroud)

FROM [Person].[Contact] AS [t0] LEFT OUTER JOIN [HumanResources].[Employee] AS [t1] ON [t1].[ContactID] = [t0].[ContactID] ORDER BY [t0].[ContactID ],[t1].[EmployeeID]

现在只查询每个Contact Contacts的供应商.选择(cont => new {cont.EmailAddress,cont.EmailPromotion,Vendors = cont.VendorContacts.Select(vend => new {vend.ContactTypeID,vend.ModifiedDate}).ToList() }).ToList()

还好吗:

SELECT [t0].[EmailAddress], [t0].[EmailPromotion], [t1].[ContactTypeID], [t1].[ModifiedDate], (
SELECT COUNT(*)
FROM [Purchasing].[VendorContact] AS [t2]
WHERE [t2].[ContactID] = [t0].[ContactID]
) AS [value]
Run Code Online (Sandbox Code Playgroud)

FROM [Person].[Contact] AS [t0] LEFT OUTER JOIN [Purchasing].[VendorContact] AS [t1] ON [t1].[ContactID] = [t0].[ContactID] ORDER BY [t0].[ContactID ],[t1].[VendorID]

现在立即查询两个(触发X行查询)

Contacts
.Select(cont=>new 
{
    cont.EmailAddress,
    cont.EmailPromotion,
    Employees = cont.Employees
        .Select(emp=>new
        {
            emp.Gender,
            emp.HireDate
        }).ToList(),
    Vendors = cont.VendorContacts.Select(vend=>new
    {
        vend.ContactTypeID,
        vend.ModifiedDate
    }).ToList()
}).ToList()
Run Code Online (Sandbox Code Playgroud)

产生丑陋和缓慢(不是因为显而易见的原因粘贴它们,但你明白了):

SELECT [t0].[EmailAddress], [t0].[EmailPromotion], [t1].[Gender], [t1].[HireDate], (
SELECT COUNT(*)
FROM [HumanResources].[Employee] AS [t2]
WHERE [t2].[ContactID] = [t0].[ContactID]
) AS [value], [t0].[ContactID]
FROM [Person].[Contact] AS [t0]
LEFT OUTER JOIN [HumanResources].[Employee] AS [t1] ON [t1].[ContactID] = [t0].[ContactID]
ORDER BY [t0].[ContactID], [t1].[EmployeeID]
GO

-- Region Parameters
DECLARE @x1 Int = 1
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO

 -- Region Parameters
DECLARE @x1 Int = 2
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO

-- Region Parameters
DECLARE @x1 Int = 3
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO

-- Region Parameters
DECLARE @x1 Int = 4
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO

-- Region Parameters
DECLARE @x1 Int = 5
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO

-- Region Parameters
DECLARE @x1 Int = 6
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO

-- Region Parameters
DECLARE @x1 Int = 7
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO

-- Region Parameters
DECLARE @x1 Int = 8
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO

-- Region Parameters
DECLARE @x1 Int = 9
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO

-- Region Parameters
DECLARE @x1 Int = 10
-- EndRegion
SELECT [t0].[ContactTypeID], [t0].[ModifiedDate]
FROM [Purchasing].[VendorContact] AS [t0]
WHERE [t0].[ContactID] = @x1
GO
Run Code Online (Sandbox Code Playgroud)

我期望/希望看到的内容:

SELECT [t0].[EmailAddress], [t0].[EmailPromotion], [t1].[Gender], [t1].[HireDate], [t2].[ContactTypeID], [t2].[ModifiedDate] ,[t0].[ContactID]
FROM [Person].[Contact] AS [t0]
LEFT OUTER JOIN [HumanResources].[Employee] AS [t1] ON [t1].[ContactID] = [t0].[ContactID]
LEFT OUTER JOIN [Purchasing].[VendorContact] AS [t2] ON [t2].[ContactID] = [t0].[ContactID]
GO
Run Code Online (Sandbox Code Playgroud)

Ron*_*dau 0

我找到了一个似乎可以处理我的核心问题(合理生成 SQL 与为子查询生成数百万条语句)的提供商,但不确定它是否合适,因为这取决于他们的答案。

http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=20658&StartAtMessage=0윎

我还应该了解其他提供商吗?如果我直到现在才错过这个,可能还有其他的,我很乐意对它们进行比较。我现在拥有的是

完全不符合我对每行没有 1 个查询的要求: - linq to SQL - linq to Entities - devart linqconnect

似乎有效 - llblgen

未经测试/需要反馈 - Telerik OpenAccess - NHibernate - Mindscape lightspeed

还有其他我应该了解的吗?