Writing LINQ Trying to create a LINQ to run in C# program - linq

I'm currently creating a dropdown and hoping to find help writing a LINQ query...
Here is the SQL I'm trying to replicate:
select
IIf
(
TA.[LeaseDeptSubmittal] IS NOT NULL
AND TA.[LeaseDeptComplete] IS NULL, 'Lease Dept',
IIf
(
TA.[CompleteDate] IS NULL
AND TA.[RequestAddtnlInfo] IS NOT NULL, 'Need Info',
IIf
(
TA.[RequestDate] IS NULL, '',
IIf
(
TA.[RequestDate] IS NOT NULL
AND TA.[CompleteDate] IS NULL, 'Pending', 'Complete'
)
)
)
) ,
Id
from Tasks TA

You can translate IIF pretty directly into the C# (LINQ) ternary conditional operator, and then you can just follow my SQL to LINQ Recipe.
var ans = from TA in Tasks
select new {
Status = (TA.LeaseDeptSubmittal != null &&
TA.LeaseDeptComplete == null)
? "Lease Dept"
: (TA.CompleteDate == null &&
TA.RequestAddtnlInfo != null)
? "Need Info"
: TA.RequestDate == null
? ""
: (TA.RequestDate != null && TA.CompleteDate == null) ? "Pending" : "Complete",
TA.Id
};
I wouldn't normally indent ?: this way, but the nesting is quite deep (and unnecessarily redundant in one case) so I moved everything left.
I would re-work it like this to remove redundant tests and clear up the logic some:
var ans = from TA in Tasks
select new {
Status = (TA.LeaseDeptSubmittal != null &&
TA.LeaseDeptComplete == null)
? "Lease Dept"
: TA.CompleteDate != null
? "Complete"
: TA.RequestAddtnlInfo != null
? "Need Info"
: TA.RequestDate != null
? "Pending"
: "",
TA.Id
};

Related

How to pass an external parameter to LINQ where clause in CRM

I have a LINQ query which works fine as for stand alone lists but fails for CRM
var lst = new List<bool?>();
lst.Add(null);
lst.Add(true);
lst.Add(false);
bool IsWet = false;
var newlst = from exch_HideVoiceSignature in lst where
(((exch_HideVoiceSignature!=null && exch_HideVoiceSignature==false
|| exch_HideVoiceSignature== null) )&& !IsWet) select exch_HideVoiceSignature;
newlst.Dump();
var question = from q in exch_questionSet where ((q.exch_HideVoiceSignature != null
&& q.exch_HideVoiceSignature.Value == 0 )|| q.exch_HideVoiceSignature == null )
&& !IsWet select q.exch_HideVoiceSignature;
question.FirstOrDefault().Dump();
As you can see I can pass the variable IsWet to LINQ query for a standard list fine and get values for first list. But when I execute the same for second list, I get the following error
Invalid 'where' condition. An entity member is invoking an invalid property or method
The CRM LINQ provider won't support the evaluation you attempting. It only supports evaluation of where criteria is evaluating an entity field.
That's not a problem. Since you want the LINQ query to only use the where clause if IsWet is false (correct me if I'm wrong on that.) So we simply do the evaluation to determine if the where clause should be added or not. Then execute your query.
var question = from q in exch_questionSet
select q.exch_HideVoiceSignature;
if (!IsWet)
{
question.Where(x => ((x.exch_HideVoiceSignature != null
&& x.exch_HideVoiceSignature.Value == 0) || x.exch_HideVoiceSignature == null));
}
question.FirstOrDefault().Dump();
I am constantly confronted with that problem.
Try to "detach" (for example call .ToArray()) your query (while it is "clear") from CRM and then filter query using external parameter. This should help.
var question =
(from q in exch_questionSet
where (
(q.exch_HideVoiceSignature != null && q.exch_HideVoiceSignature.Value == 0 ) ||
q.exch_HideVoiceSignature == null )
select q.exch_HideVoiceSignature
).ToArray().Where(q => !IsWet);
question.FirstOrDefault().Dump();
UPDATE
If you are using IsWet flag to control blocks of conditions (enable and disable them from the one point in the code) then probably you may be interested in class named PredicateBuilder which allows you to dynamically construct predicates.
Just because I had an existing query with lot of other joins etc. and I wanted to pass this additional parameter to it I ended up using a var statement which dumps the rows to a list and applies the where clause in the same statement
bool IsWet =true ;
var question = ...existing query ...
select new {
...existing output ...,
Wet =q.exch_HideVoiceSignature != null &&
q.exch_HideVoiceSignature.Value == 119080001,
Voice = q.exch_HideVoiceSignature == null ||
(q.exch_HideVoiceSignature != null &&
q.exch_HideVoiceSignature.Value == 119080000) ,
}
;
var qq = IsWet ?
question.ToList().Where(X=> X.Wet ) :
question.ToList().Where(X=> X.Voice );
qq.FirstOrDefault().Dump();

Linq query skip querying null coditions

I am very new to linq. I have my clients table. I want to select clients depending on the two conditions
Client type
Client city
So I can write the query like
from c in clients
where c.Type == cType
&& c.City == cCity
Can I use this same query to get the result only providing client type(ignoring the City condition. somithing like *).
What I want to do is if cCity or cType is null ignore the condition.
Is this possible to do?
Isn't that what you're looking for?
from c in clients
where (c.Type == null || c.Type == cType)
&& (c.City == null || c.City == cCity)
You can compose a LINQ statement before actually executing it:
if (cType != null)
clients = clients.Where(c => c.Type == cType);
if (cCity != null)
clients = clients.Where(c => c.City== cCity);
// At this point the query is never executed yet.
Example of how the query can be executed for the first time :
var results = clients.ToList();
from c in clients
where (cType == null ? 1 == 1 : c.Type == cType)
&& (cCity == null ? 1 == 1 : c.City == cCity)

Passing null as Contains() within "linq to sql" query

I have a problem with Contains in linq to sql query as below:
public IAuditRecord[] Fetch(SearchConditions searchConditions)
{
IAuditRecord[] searchedList = (from rows in _dbContex.AuditTrails
where
(searchConditions.Owner == null || searchConditions.Owner == 0) ? true : rows.Owner == searchConditions.Owner
&&
/*This line cannot compile when ActionIDs array is empty*/
(searchConditions.ActionIDs != null && searchConditions.ActionIDs.Length != 0) ? searchConditions.ActionIDs.Contains(rows.UserActionID) : true
&& ((searchConditions.StartDate != null && searchConditions.EndDate != null) ? (rows.TimeStamp >= searchConditions.StartDate && rows.TimeStamp <= searchConditions.EndDate)
: (searchConditions.StartDate != null && searchConditions.EndDate == null) ? rows.TimeStamp >= searchConditions.StartDate : (searchConditions.StartDate == null && searchConditions.EndDate != null) ? (rows.TimeStamp <= searchConditions.EndDate)
: true)
select rows).ToArray();
return searchedList;
}
This query executes perfectly if searchCondition.ActionIDs array is not null or empty,
but when i pass the ActionIDs array as null the query cannot be compiled.
So the main question is Why contains cannot work when ActionIDs array is null?
You're building an IQueryable, which defines how to query for something, not actually doing it. To do this it builds an Expression, which defines all the query intents and can later be called to actually get the data. If you were using LINQ-to-Objects, this would likely work since it would likely call searchConditions.ActionIDs != null first, then know that it doesn't have to attempt to execute the second portion. Linq-to-Entities/SQL, etc. don't have that benefit.
Long story short, you can either do:
searchConditions.ActionIDs = searchConditions.ActionIDs ?? new int[];
Or do a different query if its null, like:
var query = _dbContext.AuditTrails;
if(searchConditions.ActionIDs != null && searchCondition.ActionIDs.Length != 0)
{
query = // Further filtered query where ActionIDs are taken into account.

Linq using nullable datetime field

I have a problem with LINQ (using EF - 4.3.1.0) using the following:
DateTime? dtcollected = DateTime.TryParse(dateCollected, out dateVal) ? dateVal : (DateTime?)null;
DateTime? dtanalyzed = DateTime.TryParse(dateanalyzed, out dateVal) ? dateVal : (DateTime?)null;
var doesexist = (from pw in dbContext.WtTbl
where pw.CompanyId == 13
&& pw.DateCollected == dtcollected
&& pw.DateAnalyzed == dtanalyzed
select pw).Any();
Note that dateCollected came in as a string so I had to convert it to a nullable DateTime. Same goes for dateanalyzed.
What I am struck at is that I have a companyId of 13. A null value of dtcollected. And a value for dtanalyzed already in the table so I would expect doesexist to return true, but it returns false.
If I comment out
var doesexist = (from pw in dbContext.WtTbl
where pw.CompanyId == 13
// && pw.DateCollected == dtcollected
&& pw.DateAnalyzed == dtanalyzed
select pw).Any();
or put:
var doesexist = (from pw in dbContext.WtTbl
where pw.CompanyId == 13
&& pw.DateCollected == null
&& pw.DateAnalyzed == dtanalyzed
select pw).Any();
Then I get a true. How come it is not able to comprehend null value of dtcollected?
Am I doing something wrong.
In most database systems (definitely SQL Server), if one side of the comparison is null, then the result of the comparison is unknown, and therefore not included in the result set (or, for all intents and purposes, false).
That said, you need to perform a check for null against your variables, only checking against the database field if the parameter is non-null, like so:
var doesexist = (
from pw in dbContext.WtTbl
where
pw.CompanyId == 13 &&
(dtcollected == null || pw.DateCollected == dtcollected) &&
(dtanalyzed == null || pw.DateAnalyzed == dtanalyzed)
select pw).Any();
This translates roughly to:
declare #dtcollected date = null
declare #dtanalyzed date = null
select
*
from
Table as t
where
(#dtcollected is null or t.DateCollected = #dtcollected) and
(#dtanalyzed is null or t.DateAnalyzed = #dtanalyzed)

How set XAttribute Value null

XElement xml = new XElement("MyMenu",
from c in db.Security_Module_Menus
//where (c.ParentID == 0)
orderby c.Menu_ID
select new XElement("Item",
new XAttribute("Text", c.Menu_Name), new XAttribute("NavigateUrl", c.Target_URL)
)
);
From my above syntax c.Menu_Name,c.Target_URL values are nullable.Show me the error
Value cannot be null.
Parameter name: value I know SetElementValue() used to solve this error.But how can i use to my above syntax.Help me to Use it.Show me syntax
Presumably you want to avoid creating the attributes if c.Menu_Name and c.Target_URL are null? If so, you can do it as follows:
new XElement("MyMenu",
from c in db.Security_Module_Menus
orderby c.Menu_ID
select new XElement("Item",
c.Menu_Name == null ? null : new XAttribute("Text", c.Menu_Name),
c.Target_URL == null ? null : new XAttribute("NavigateUrl", c.Target_URL))
)

Resources