i have my records as follows
mazhar-kaunain-baig-5
mazhar-kaunain-baig-5-6
mazhar-kaunain-baig
this is my query
ptype = _pagecontext.PagesRefs
.Where(m => m.nvcr_Slug.Contains(str+ "-") && m.bit_Active == true)
.ToList();
correct results:
1) str=mazhar-kaunain-baig
bring back
mazhar-kaunain-baig-5
mazhar-kaunain-baig-5-6
2) str=mazhar-kaunain
bring back nothing
3) str=mazhar
bring back nothing
the contains and equals becomes invalid in this scenario . how could i achieve the following result where i have the exact matching of the pattern.
take out the +"-"?
sRefs.Where(m => m.nvcr_Slug.Contains(str) && m.bit_Active == true).ToList();
This will return the exact results you mentioned in situation 1, 2 and 3.
var result = from d in data
let remainingString = d.Slug.Remove(0, Math.Min(text.Length + 1, d.Slug.Length))
where remainingString.Length > 0 && Char.IsDigit(remainingString[0])
select d;
why don't you use StartsWith instead ?
Determines whether the beginning of this string instance matches the specified string.
.Where(m => m.nvcr_Slug.StartsWith(str) && m.bit_Active == true).ToList();
more info at:
http://msdn.microsoft.com/en-us/library/baketfxw.aspx
Related
Below is my LINQ query:
list = (from i in context.Cars
.Where(c => terms.All(t => c.Code.Contains(t) || c.ShortDescription.Contains(t)
&& c.Code.Replace(" " , "").Length >3))
select new Model.Cars
{
CarId = i.CarId,
ShortDescription = i.ShortDescription,
Code = i.Code
}).Take(250).ToList();\
One of the business requirement is to exclude any record where code length is shorter than 3. A lot of these codes have whitespaces in them which is why I put in clause of replacing " " with "". This does not seem to work in my query. I am still getting results where code length is 3. I should only get results where code length is greater than3. It almost seems like the replace is not replacing whitespaces with no space. Everything else works. What am I doing wrong ?
Operator precedence strikes again.
.Where(c =>
terms.All(t =>
( c.Code.Contains(t) || c.ShortDescription.Contains(t) )
&& c.Code.Replace(" " , "").Length > 3
)
)
if (true || true && false)
MessageBox.Show("Gotcha!");
Why are you switching bewteen LINQ & lambda syntax? Had you stuck to the LINQ syntax, you probably would have spotted the precedence problem:
list = (from i in context.Cars
let code = i.Code.Trim()
where terms.All(t => code.Contains(t) || i.ShortDescription.Contains(t))
&& code.Length > 3
select new Model.Cars
{
CarId = i.CarId,
ShortDescription = i.ShortDescription,
Code = code
}).Take(250).ToList();
I have a query like this :
result =
firstIdeaRepository.FindBy(
i => i.FirstIdeaState == FirstIdeaState && i.Date >= start && i.Date <= end)
.AsEnumerable()
.Select(j => new RptListOfCompanyBasedOnFirstIdeaState()
{
Name =
companyRepository.FindBy(i => i.UserId == j.UserId)
.FirstOrDefault()
DateOfMeeting =
calenderRepository.ConvertToPersianToShow(
meetingReposiotry.FindBy(s => s.FirstIdeaId == j.Id)
.FirstOrDefault()
.Date),
DateOfExit =
calenderRepository.ConvertToPersianToShow(j.DateOfExit.Value),
ReasonOfExit = j.ReasonOfExit,
}).ToList();
return result;
As you can see i use FirstOrDefault() and j.DateOfExit.Value and sometimes my Date doesn't have any values or sometime my other variables are null too because i use firstordefaut() like
companyRepository.FindBy(i => i.UserId == j.UserId).FirstOrDefault().
So my query throws a null exception and the result can't be created ,how can i handle this exception and for example if the .NET detects the null value ignores it by default or uses a default values for that ?
Best regards.
I would make the following changes:
result =
firstIdeaRepository.FindBy(
i => i.FirstIdeaState == FirstIdeaState && i.Date >= start && i.Date <= end)
.AsEnumerable()
.Select(j => new RptListOfCompanyBasedOnFirstIdeaState()
{
Name =
companyRepository.FindBy(i => i.UserId == j.UserId)
.FirstOrDefault()
DateOfMeeting =
callenderRepository.ConvertToPersianToShow(
meetingReposiotry.FindBy(s => s.FirstIdeaId == j.Id)
// project a new sequence first, before calling `FirstOrDefault`:
.Select(s => s.Date)
.FirstOrDefault(),
DateOfExit =
j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value) :
null,
ReasonOfExit = j.ReasonOfExit,
}).ToList();
When you use FirstOrDefault, there's a possibility that you'll get null back (in the case of reference types), and so you need to plan for that in your code.
For example, when assigning DateOfMeeting, you could project the results (using .Select) before using .FirstOrDefault, so that you're not ever accessing the Date property on what could be a null value.
As for DateOfExit, I've used the conditional operator to determine whether to call the calendarRepository's method at all. This assumes that DateOfExit is nullable.
Unrelated: "Calendar" is spelled with one "l" and not two.
Since you're using a nullable date, you can try filtering by values that have date, something like:
.FindBy(s => s.FirstIdeaId == j.Id && s.Date.HasValue)
This will ensure that you don't get any records with null date.
As I mentioned in comments, other cases need to be handled on case-by-case basis. Judging by the code you've shown, maybe you can handle Name as:
Name = companyRepository.FindBy(i => i.UserId == j.UserId).FirstOrDefault() ?? "anonymous";
and so on.
Another example:
If you do want to get the record even if DateOfMeeting is null, then add a check for HasValue in subsequent part or default it to some date:
DateOfExit = j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value)
: (DateTime)null, // you need to make `DateOfExit` nullable and then handle that downstream
// or (default with current date)
DateOfExit = j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value)
: callenderRepository.ConvertToPersianToShow(DateTime.Now),
// or (default with empty date)
DateOfExit = j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value)
: callenderRepository.ConvertToPersianToShow(new DateTime()),
Moral of the story: figure out what the default value should be in case of null and then substitute that accordingly in the query when calling FirstOrDefault().
The broadest solution would be to use the idea of an null object with the DefaultIfEmpty<T>(T DefaultValue) method in your query. An example would be:
var defaultMeeting = new Meeting() { Date = new DateTime() };
var dateOfMeeting = meetingRepository.FindBy(s => s.FirstIdeaId == j.Id)
.DefaultIfEmpty(defaultMeeting)
.FirstOrDefault()
.Date;
I use HtmlAgilityPack to get data from a website for a hobby project. I want to get the shoe article number from a site that sells shoes.
But my linq query doesn't return a string. Instead it returns the type:
System.Linq.Enumerable.WhereSelectEnumerableIterator<HtmlAgilityPack.HtmlNode,string>
How can I get the query to simply return a string?
foreach (var node in query)
{
Shoe shoe = new Shoe();
var num = from x in node.Descendants()
where x.Name == "img" && x.Attributes.Contains("class") && x.Attributes["class"].Value == "thumb lazy"
select x.Attributes["title"].Value.Substring(11);
shoe.articleNumber = Convert.ToInt32(num); //error
shoes.Add(shoe);
}
The error: InvalidCastException was unhandled.
Unable to cast object of type
'WhereSelectEnumerableIterator`2[HtmlAgilityPack.HtmlNode,System.String]'
to type 'System.IConvertible'.
Your LINQ query returns a collection. Use First/FirstOrDefault/Single/SingleOrDefault to get only one element from the collection:
var num = (from x in node.Descendants()
where x.Name == "img" && x.Attributes.Contains("class") && x.Attributes["class"].Value == "thumb lazy"
select x.Attributes["title"]).First().Value.Substring(11);
Assuming there's only going to be one entry that matches your query, you just need to modify it to use FirstOrDefault() or First():
foreach (var node in query)
{
Shoe shoe = new Shoe();
var num = (from x in node.Descendants()
where x.Name == "img" && x.Attributes.Contains("class") && x.Attributes["class"].Value == "thumb lazy"
select x.Attributes["title"].Value.Substring(11)).First();
shoe.articleNumber = Convert.ToInt32(num);
shoes.Add(shoe);
}
Just bear in mind that the above will fail with an exception if the item is not present.
your query does not return a single result but a list of results. In your case this will be a list containing a single id. You should modify it to this:
var num = (from x in node.Descendants()
where x.Name == "img" && x.Attributes.Contains("class") && x.Attributes["class"].Value == "thumb lazy"
select x.Attributes["title"].Value.Substring(11)).FirstOrDefault();
Difference between single, singleorDefault ,first ,FirstorDefault
Here
I have a dictionary in my C# program that contains a list of Key + Values.
The values are itemid, Month, Year, Count
I would like to query the dictionary by comparing a set of values (itemid, Month, Year) and return true or false if a the specific itemid + Month + Year exist.
So if all 3 values (itemid + Month + Year) exist return true else return false.
I tried something like this
(if (myd.Select(d => d.Value.itemid == item.itemid && d.Value.Month == DateRange.Month && d.Value.Year == DateRange.Year).ToString() != "")
The above didn't work.
You seem to misunderstand the usage of the Select() method. Select creates a "projection"; given an input collection (enumerable) of elements, it produces an output enumerable that is equal in cardinality, but is composed of elements that are each the result of a transformation of the corresponding element of the input.
What you need is either a Where() method (which returns a list, lesser or equal in cardinality to the input, of the elements from the input for which a boolean condition is true), or an Any() method (which returns a single "true" or "false" if any of the elements in the input meet the condition):
if(myd.Where(d => d.Value.itemid == item.itemid
&& d.Value.Month == DateRange.Month
&& d.Value.Year == DateRange.Year).Count() >= 1)
...
//produces the equivalent result but generally performs faster
if(myd.Any(d => d.Value.itemid == item.itemid
&& d.Value.Month == DateRange.Month
&& d.Value.Year == DateRange.Year))
...
If like linq-Syntax, this checks if at least one item that satisfies all three condition exists:
if((from d in myd
where d.Value.itemid == item.itemid
&& d.Value.Month == DateRange.Month
&& d.Value.Year == DateRange.Year).FirstOrDefault() != null)
You'll need to create a 2nd dictionary if you want to do lookups with another key (in this case itemid,month,year, probably placed into a Tuple), and you'll need to maintain them both whenever you add/remove from either.
use Where to filter (I'm assuming the condition in your code is defined correctly... you haven't given us enough info to evaluate that)
var filteredDictionary = myd.Where(d => d.Value.itemid == item.itemid && d.Value.Month == DateRange.Month && d.Value.Year == DateRange.Year)
use Select to transform from a KeyValuePair to just a value
var filteredValues = filteredDictionary.Select(x=>x.Value)
use Any to return a bool of whether or not an item exists
bool matchExists = myd.Any(d => d.Value.itemid == item.itemid && d.Value.Month == DateRange.Month && d.Value.Year == DateRange.Year)
Any is going to be most efficient for the problem you describe because it will stop evaluating items in the dictionary and return True as soon as a match is found
If you are working with .NET 4.0 you can use Tuples as keys.
var dict = new Dictionary<Tuple<int,int,int>,MyValueType>();
You can then test if a value exists with
var key = new Tuple<int,int,int>(item.itemid, DateRange.Month, DateRange.Year);
if(dict.ContainsKey(key)) {
...
}
Or you can test
if(dict.ContainsValue(referenceValue)) {
...
}
You will have to pass it a reference value containing what you are looking for. Make sure that your value type implements EqualityComparer<T>.
The first method will be much faster, since the dictionary is accessed by the key. If you are not accessing the dictionary by the key, you could use a List<T> as well.
I have the following LINQ expression that's not returning the appropriate response
var query = from quote in db.Quotes
where quote.QuoteStatus == "Estimating" || quote.QuoteStatus == "Rejected"
from emp in db.Employees
where emp.EmployeeID == quote.EmployeeID
orderby quote.QuoteID descending
select new
{
quote.QuoteID,
quote.DateDue,
Company = quote.Company.CompanyName,
Attachments = quote.Attachments.Count,
Employee = emp.FullName,
Estimator = (quote.EstimatorID != null && quote.EstimatorID != String.Empty)
? db.Employees.Single (c => c.EmployeeID == quote.EstimatorID).FullName
: "Unassigned",
Status = quote.QuoteStatus, Priority = quote.Priority
};
The problem lies in the Estimator = (quote.EstimatorID != null && quote.EstimatorID != String.Empty) ? db.Employees.Single(c => c.EmployeeID == quote.EstimatorID).FullName : "Unassigned" part.
I NEVER get it to evalueate to "Unassigned", on the ones that are supposed to, it just returns null. Have I written this wrong?
Try this and see if you're receiving the same values:
Estimator = ((!string.IsNullOrEmpty(quote.EstimatorID) && !string.IsNullOrEmpty(quote.EstimatorID.Trim())
? (db.Employees.Single(c => c.EmployeeID == quote.EstimatorID)).FullName
: "Unassigned")
If that doesn't work, try replacing the check in the ternary expression (!string.IsNullOrEmpty part) with false and see if you reach "Unassigned". I've found that sometimes, when you use a ternary expression in a LINQ query, you have to wrap the whole thing in parentheses.
I think your expression is correct, although I would advise changing it to !string.IsNullOrEmpty(quote.EstimatorID) for clarity.
Note however that your expression could still return null if db.Employees.Single(c => c.EmployeeID == quote.EstimatorID).FullName returns null.
Then it looks like quote.EstimatorID is not null or empty string. Is db.Employees.Single() returning null here? Debug it - put breakpoints into those parts of the expression (putting them on separate lines, if necessary). If you can't do that wrap methods around them that call Debug.WriteLine() or similar.