I have this subsonic query:
Select.AllColumnsFrom<Data.Group>()
.Where(Data.Group.GroupIDColumn).IsNotEqualTo(m_sRootGroupID)
.AndExpression(Data.Group.Columns.OwnerPersonID).IsEqualTo(gUserID)
.OrExpression(Data.Group.Columns.OwnerPersonID).IsEqualTo(gUserContextID)
.AndExpression(Data.Group.Columns.IsCallList).IsEqualTo(true)
.CheckLogicalDelete().ExecuteTypedList<Groups>();
At first sight, it seems that the previous developer has mistaken AndExpression
for And
. I know that AndExpression
encloses the preceding statements inside parentheses.
How is the above subsonic query be translated into SQL?
This is what I'm thinking:
SELECT *
FROM tblGroups
WHERE GroupID <> m_sRootGroupID
AND ( --first [AndExpression]
OwnerPersonID = `gUserID
OR ( -- [OrExpression]
OwnerPersonID = gUserContextID
AND ( -- second [AndExpression]
IsCallList = true
)
)
) -- first [AndExpression]
AND ISNULL(IsDeleted,0) = 0
How is the ..Expression
s being handled if there is no CloseExpression
?
As has been pointed out by @MikeWalsh in his answer, calling .ToString()
shows what the subsonic query looks like when translated to SQL.
Thus, the above code can be translated into:
SELECT * --subsonic specifies all columns
FROM [dbo].[tblGroups]
WHERE [dbo].[tblGroups].[GroupID] <> @GroupID0
AND ([dbo].[tblGroups].[OwnerPersonID] = @OwnerPersonID1
)
OR ([dbo].[tblGroups].[OwnerPersonID] = @OwnerPersonID3
)
AND ([dbo].[tblGroups].[IsCallList] = @IsCallList5
)
AND ([dbo].[tblGroups].[IsDeleted] IS NULL OR [dbo].[tblGroups].[IsDeleted] = 0)
Which tells us that calling AndExpression
/OrExpression
without a CloseExpression
, subsonic assumes there is only one condition inside the AND
statement enclosed in parentheses, thus:
.AndExpression(Data.Group.Columns.OwnerPersonID).IsEqualTo(gUserID)
is translated into:
AND ([dbo].[tblGroups].[OwnerPersonID] = @OwnerPersonID1)
EDIT:
That's what I thought. However, when using this subsonic query:
Select.AllColumnsFrom<Data.Group>()
.Where(Data.Group.GroupIDColumn).IsNotEqualTo(m_sRootGroupID)
.AndExpression(Data.Group.Columns.OwnerPersonID).IsEqualTo("someownerID")
.Or(Data.Group.Columns.OwnerPersonID).IsEqualTo("SomeContextID")
.AndExpression(Data.Group.Columns.IsCallList).IsEqualTo(true)
.CheckLogicalDelete().ToString();
I got this query (formatting mine):
SELECT <All columns>
FROM [dbo].[tblGroups]
WHERE [dbo].[tblGroups].[GroupID] <> @GroupID0
AND ( -- first [AndExpression]
[dbo].[tblGroups].[OwnerPersonID] = @OwnerPersonID1 --Data.Group.Columns.OwnerPersonID).IsEqualTo("someownerID")
OR [dbo].[tblGroups].[OwnerPersonID] = @OwnerPersonID2 --.Or(Data.Group.Columns.OwnerPersonID).IsEqualTo("SomeContextID")
) -- close for first [AndExpression]
AND ( -- second [AndExpression]
[dbo].[tblGroups].[IsCallList] = @IsCallList4
) -- close for second [AndExpression]
AND ([dbo].[tblGroups].[IsDeleted] IS NULL OR [dbo].[tblGroups].[IsDeleted] = 0)
As you can see, the first AndExpression
includes .Or(Data.Group.Columns.OwnerPersonID).IsEqualTo("SomeContextID")
inside its parentheses, which implies that ..Expression
's continue to include preceding statements inside the parentheses until it finds another ..Expression
(as we can observe on the second AndExpression
.
Adding additional And
/Or
methods after the first AndExpression
strengthens the proof that
Using
..Expression
's withoutCloseExpression
will encapsulate preceding statements in parentheses until another..Expression
is called.