-1

SQL 查询如下所示,但使用实体框架?

SELECT     Software.Vendor, Software.Version, 
Rollout.ID, Software.Name, Rollout.Name 

FROM         org_User INNER JOIN
                      SoftwareUser ON org_User.ID = SoftwareUser.FK_org_User_ID INNER JOIN
                      Software ON Software.ID = SoftwareUser.FK_Software_ID INNER JOIN
                      AssetAssignee ON org_User.ID = AssetAssignee.FK_org_User_ID INNER JOIN
                      Rollout ON AssetAssignee.FK_Rollout_ID = Rollout.ID INNER JOIN
                      Location ON AssetAssignee.FK_Location_ID = Location.ID
WHERE     (Rollout.ID = 44) AND (Location.ID = 2)
GROUP BY Software.Vendor, Software.Version, 
Rollout.ID, Software.Name, Rollout.Name 

DB Schema(注意多对多表'SoftwareUser') 数据库模式

实体框架 edmx 模型(多对多表 'SoftwareUser' 未显示,因为设计者承认它只是一个纯粹的多对多链接表,并用两端带有星号的连接线来说明这一点)

在此处输入图像描述

我尝试使用 PredicateBuilder 实用程序类,但我在下面的做法显然是非常错误的,因为我无法让它以我使用它的方式构建查询。所以那里没有快乐。

 internal static List<Software> GetApplications(
        string UserID,
        string Surname,
        string Forname,
        int? TeamID,
        int? LocationID,
        int? RolloutID,
        string EmployeeID)
    {
        {
            var predicate = GetApplicationsPredicate(UserID, Surname, Forname, TeamID, LocationID, RolloutID, EmployeeID);

            using (ITAMEFContext db = new ITAMEFContext(ConnectionStrings.ITAM_ConnectionString_EF))
            {
                db.Configuration.ProxyCreationEnabled = false;

                return db.Softwares.Where(predicate).ToList();

            }
        }
    }

    private static Expression<Func<Software, bool>> GetApplicationsPredicate(
        string UserID,
        string Surname,
        string Forname,
        int? TeamID,
        int? LocationID,
        int? RolloutID,
        string EmployeeID)
    {
        var predicate = PredicateBuilder.True<Software>();

        bool nothingSelected = (
            TeamID == null
            && LocationID == null
            && RolloutID == null
            && string.IsNullOrEmpty(Surname)
            && string.IsNullOrEmpty(Forname)
            && string.IsNullOrEmpty(EmployeeID)
            && string.IsNullOrEmpty(UserID)
            );

        if (nothingSelected)
        {
            // we need to negate the first true predicate of we don't have any other predicates.
            predicate = predicate.And(u => !(nothingSelected));
            return predicate;
        }

        //if (!string.IsNullOrEmpty(UserID))
        //    predicate = predicate.And(s => s.org_User.Select(u => u.AssetAssignees.Any(aa => aa.org_User.DomainUserID.Contains(UserID))) != null);

        //if (!string.IsNullOrEmpty(Surname))
        //    predicate = predicate.And(s => s.org_User.Any(u => u.AssetAssignees.Any(aa => aa.org_User.Surname.Contains(Surname))));

        //if (!string.IsNullOrEmpty(Forname))
        //    predicate = predicate.And(s => s.org_User.Any(u => u.AssetAssignees.Any(aa => aa.org_User.Forename.Contains(Forname)))); ;

        //if (!string.IsNullOrEmpty(EmployeeID))
        //    predicate = predicate.And(s => s.org_User.Any(u => u.AssetAssignees.Any(aa => aa.org_User.EmployeeID.Contains(EmployeeID))));

        if (LocationID.HasValue)
            predicate = predicate.And(s => s.org_User.Any(u => u.AssetAssignees.Any(aa => aa.Location.ID == LocationID.Value)));

        //if (TeamID.HasValue)
        //    predicate = predicate.And(s => s.org_User.Any(u => u.AssetAssignees.Any(aa => aa.org_User.org_Team.ID == TeamID.Value)));

        if (RolloutID.HasValue)
            predicate = predicate.And(s => s.org_User.Any(u => u.AssetAssignees.Any(aa => aa.Rollout.ID == RolloutID)));

        //if (RolloutID.HasValue)
        //    predicate = predicate.And(s => s.org_User.Any(u => u.AssetAssignees.Any(aa => aa.Rollout.ID == RolloutID)));

        return predicate;
    }

但这只会导致生成以下不适当的 SQL。

    SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[FK_ApptrackerID] AS [FK_ApptrackerID], 
[Extent1].[FK_SoftwareType_ID] AS [FK_SoftwareType_ID], 
[Extent1].[Name] AS [Name], 
[Extent1].[Vendor] AS [Vendor], 
[Extent1].[Version] AS [Version], 
[Extent1].[Ready] AS [Ready]
FROM [dbo].[Software] AS [Extent1]
WHERE 
( EXISTS (SELECT 
    1 AS [C1]
    FROM ( SELECT 
        [Extent2].[FK_org_User_ID] AS [FK_org_User_ID]
        FROM [dbo].[SoftwareUser] AS [Extent2]
        WHERE [Extent1].[ID] = [Extent2].[FK_Software_ID]
    )  AS [Project1]
    WHERE  EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[AssetAssignee] AS [Extent3]
        WHERE ([Project1].[FK_org_User_ID] = [Extent3].[FK_org_User_ID]) AND ([Extent3].[FK_Location_ID] = 2)
    )
)) 

AND 

( EXISTS (SELECT 
    1 AS [C1]
    FROM ( SELECT 
        [Extent4].[FK_org_User_ID] AS [FK_org_User_ID]
        FROM [dbo].[SoftwareUser] AS [Extent4]
        WHERE [Extent1].[ID] = [Extent4].[FK_Software_ID]
    )  AS [Project4]
    WHERE  EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[AssetAssignee] AS [Extent5]
        WHERE ([Project4].[FK_org_User_ID] = [Extent5].[FK_org_User_ID]) AND ([Extent5].[FK_Rollout_ID] = 44)
    )
))

请帮忙 :'(

EF dll 版本 4.4.0.0 | 方法 - 数据库优先 | .net 4.0

4

2 回答 2

1

有些查询无法在 EF 中编写,但您显示的查询实际上并不难,尤其是。当您使用查询语法并利用导航属性的强大功能时不会:

from ou in db.org_User
from sw in ou.Softwares
from aa in ou.AssetAssignees
select new { sw.Vendor, sw.Version, aa.Rollout.ID, aa.Rollout.Name }

您不需要,group by因为您选择的字段与您分组的字段完全相同。您也不需要访问联结表,因为 EF 会为您进行连接。

如果要应用谓词,可以通过以下方式开始语句

from ou in db.org_User.Where(predicate)
于 2013-07-05T22:17:32.433 回答
0

我最终确定了以下查询语法,这似乎可以带回正确的结果。

internal static List<Software> GetApplications(
            string UserID,
            string Surname,
            string Forname,
            int? TeamID,
            int? LocationID,
            int? RolloutID,
            string EmployeeID)
        {
            {

                using (ITAMEFContext db = new ITAMEFContext(ConnectionStrings.ITAM_ConnectionString_EF))
                {
                    db.Configuration.ProxyCreationEnabled = false;

                    return (from ou in db.org_User
                           from sw in ou.Softwares
                           from aa in ou.AssetAssignees
                           where aa.org_User.DomainUserID.Contains(UserID)
                           &&
                           (!TeamID.HasValue || aa.org_User.org_Team.ID == TeamID)
                           &&
                           (!LocationID.HasValue || aa.org_User.Location.ID == LocationID.Value)
                           &&
                           (!RolloutID.HasValue || aa.Rollout.ID == RolloutID)
                           &&
                           aa.org_User.Surname.Contains(Surname)
                           &&
                           aa.org_User.Forename.Contains(Forname)
                           &&
                           aa.org_User.EmployeeID.Contains(EmployeeID)
                           group sw by sw.ID into swG

                           select swG).Select(g => g.FirstOrDefault()).ToList();

                }
            }
        }
于 2013-07-08T09:53:41.907 回答