Need help with a LINQ ArgumentOutOfRangeException in C# - c#

Hoping this is a nice softball of a question for a friday but I have the following line of code:
//System.ArgumentOutOfRangeException generated if there is no matching data
currentAnswers = new CurrentAnswersCollection()
.Where("PARTICIPANT_ID", 10000).Load()[0];
CurrentAnswersCollection is a strongly-typed collection populated by a view going back to my database.
The problem of course is that if there is not a corresponding PARTICIPANT_ID = 10000 I get the error message.
Is there a better way to write this so that I wouldn't get the error message at all?
I just dont know enough about LINQ syntax to know if I can test for the existance first?
thanks.

Use this:
currentAnswers = new CurrentAnswersCollection()
.Where("PARTICIPANT_ID", 10000).Load()
.FirstOrDefault();
It'll return null if there is no first element.
But you may need to fix your code (replicated here) first - the .Where syntax looks dodgy.

The ArgumentOutOfRangeException is occurring when you try to use the indexer to get the first item from the (empty) list. Using the FirstOrDefault() extension method is a convenient way to return the first element of a collection, if there is one, otherwise to return null.
currentAnswers = new CurrentAnswersCollection().Where("PARTICIPANT_ID", 10000)
.Load()
.FirstOrDefault();
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.firstordefault.aspx

Try:
var answers = new CurrenAnswersCollection().Where("PARTICIPANT_ID", 10000);
if(answers.Count() >= 1) currentAnswers = answers.Load()[0];
or something similar.

You need a lambda expression in .Where.
currentAnswers = new CurrentAnswersCollection()
.Where(c => c.PARTICIPANT_ID == 10000).Load().FirstOrDefault();

Related

Check a List of a class for a specific variable with LINQ

To simplify the problem i have a List of a certain class:
class alarm{
public bool present;
}
List<alarm> alarms;
Now in some code following this i want to check if any alarm in this List has present set to true, so instead of making a for loop i want to solve it using LINQ. Can anybody give me some pointers about this in LINQ because i cant get the hang of it.
You can just use Any method:
var result = alarms.Any(a => a.present);
There are many options, the simplest would be the:
alarms.Any(x => x.present == true)
But you can use also for example:
alarms.Where(x => x.present == true).ToList().Count > 0
it is basic question about linq, you should google it first:
var query = alarms.Where(x => x.present);

Linq - Distinct list of object fill in int array

I am trying to do, get randomly one of "list of objects" from all lists.
I am getting NullReferenceException I also tried List couldn't make it work.
List<BL.Test.Test> Tests = BL.Test.GET.TestGroup(CategoryId);
// NullReferenceException on the line below:
int[] Groups = Tests.Select(d => d.TestGroupId).Distinct().ToArray();
Session["TestGroup"] = Tests.Select(t => t.TestGroupId = Groups[rnd.Next(Groups.Length)]);
Obviously, BL.Test.GET.TestGroup is the method which returns null.
That's the most probable explanation for a NullReferenceException in a second line of your example.
And if Select, Distinct and ToArray are extension methods declared in System.Linq, this reason is the only possible, so check your method.
UPD.
Sorry guys, I am wrong.
TestGroupId member of BL.Test.Test class is missed.
UPD-2
This is a good example of community debugging question. As I know it is not appreciated here
Since TestGroupId would be null hence null.Distinct() throws NullArgumentReference exception.
Change ur code with following code:
List<BL.Test.Test> Tests = BL.Test.GET.TestGroup(CategoryId);
int[] Groups = Tests.Where(d=>d.TestGroupId.HasValue).Select(d => d.TestGroupId).Distinct().ToArray();
Session["TestGroup"] = Tests.Select(t => t.TestGroupId = Groups[rnd.Next(Groups.Length)]);
Make use of HasValue to find if TestGroupId has some value.

How to use a dynamically-created string as a WHERE condition in Linq

I've to create method which returns IQueryable, and tor depends on exact type.
Is it possible to prepare any criteria which could be used after WHERE statement to get that?
for example, if T == License i use "c.fkCustomer == Organization.Customer"
if T== People , I use "c.fkPeople== Organization.People" etc.
XPQuery<T> cQuery = new XPQuery<T>(cSession);
IQueryable CurrQr = from c in cQuery
where "c.fkCustomer == Organization.Customer"
select c;
Can someone suggest something, how to achieve this goal?
I think you would be better off to use a lambda as an argument here rather than dynamic linq eg.
public IQueriable<T> MyQuery<T>(Expression<Func<T, bool>> predicate)
{
return new XPQuery<T>(cSession).Where(predicate)/*and any other bits you want at the moment this is a straight up where clause so kinda pointless*/;
}
then you can call it with:
MyQuery(c=> c.fkCustomer == Organization.Customer)
or
MyQuery(c=> c.fkPeople == Organization.People)
Yes, this can be done. One way to do this is to use the Dynamic Query Library which you can find here along with detailed information on how to use it:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

LINQ to returns count even the list is empty

I have this block of code inside another LINQ statement.
VideoLinks = (from video in m.VideoLinks.DefaultIfEmpty(new VideoGallery())
orderby video.CreatedDate
select new VideoGallery()
{
Source = video.Source,
Type = video.Type,
Links = video.Links,
Title = video.Title
}).ToList()
unfortunately if dont use DefaultIfEmpty its through me an exception. If I use DefaultIfEmpty i give count as 1 for videolinks even if m.VideoLinks is null.
So now how can avoid getting count 1 if m.VideoLinks is null
DefaultIfEmpty is going to give you a default value. It counts as an item when you call ToList() on it...thus your count is 1.
This looks like you are using linq-to-objects, so you should add a where video != null
VideoLinks = (from video in m.VideoLinks
where video != null
orderby video.CreatedDate
select new VideoGallery()
{
Source = video.Source,
Type = video.Type,
Links = video.Links,
Title = video.Title
}).ToList()
wllmsaccnt is correct - your problem is the "DefaultIfEmpty" portion of your statement. By definition, you are requesting that there be at least one item in the collection, according to the definition of this method:
Returns the elements of the specified sequence or the specified value
in a singleton collection if the sequence is empty
I think the important question here is what exception are you receiving when you don't use DefaultIfEmpty? If you tell us that, perhaps we can help you avoid it...

Best practice of SingleOrDefault()

I want to make my code better. Can I safely rewrite the first example to the second?
IQueryable<PDF> pdfList = (from pdfobj in pdfDataContext.PDFs
where pdfobj.Id == pdfId
select pdfobj);
if (pdfList.Count() > 0)
{
PDF pdfOldWay = pdfList.FirstOrDefault();
pdfOldWay. // do something. (pdfOldWay can't be null here...)
}
--
PDF pdfNewWay = (from pdfobj in pdfDataContext.PDFs
where pdfobj.Id == pdfId
select pdfobj).SingleOrDefault();
if (pdfNewWay != null)
{
// do something
}
--
EDIT:
Sorry for not being clear. My issue is to get the PDF object out directly without having to use a list first. I don't want to make a check for count is greater than 0 and because it just doesn't look good.
Yes, that looks safe. You can also simplify your query slightly:
PDF pdfNewWay = pdfDataContext.PDFs.SingleOrDefault(p => p.Id == pdfId);
if (pdfNewWay != null)
{
// do something
}
The only difference between SingleOrDefault and FirstOrDefault is that SingleOrDefault will throw an exception if more than one match is found, so unless you want this check then you may as well stick to FirstOrDefault.
You should use FirstOrDefault in the second case too as SingleOrDefault will throw an exception if there is more than one item. Is that ok for you?
On the other hand if you want to guarantee that there is only one pdfobject for some id than using SignleOrDefault is better.
If it's guaranteed that it always has 0 or 1 rows, then sure, SingleOrDefault is the best solution.
Yes you will achieve the same result, I don't see any issue.

Categories

Resources