SQL查询,例如下面的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
答案 0 :(得分: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)
答案 1 :(得分: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();
}
}
}