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.
Related
Im creating a line object which is an entity it has a Tags navigation property which I also want to set. I want to get this tags collection from a datagridview bound to Tag objects :
dgvTags.DataSource = _rs.Tags.Where(x => x.TagGroup.Name == "All Reasons").OrderBy(x => x.Name);
Code with issue :
Line l = new Line
{
Part = o.Part,
Description = desc,
Price = o.Price.Value,
InvoiceNo = o.InvoiceNo,
Cost = o.Cost.Value,
Comments = txtComment.Text,
Tags = dgvTags.SelectedRows as List<Tag> // <--- needs work here
};
The line is showing an error :
Error 5 Cannot convert type 'System.Windows.Forms.DataGridViewSelectedRowCollection' to 'System.Collections.Generic.List' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion C:\SVN\RS\fAddLines.cs 142 15 RS
Is there a correct way of doing this?
UPDATE:
Ive been able to acheive the desired result with the code below, but still looking for the correct way to do it :
foreach (DataGridViewRow r in dgvTags.SelectedRows)
{
l.Tags.Add(r.DataBoundItem as Tag);
}
Credit to David Hall he tried very hard, but in the end the code below was the simplest solution :
foreach (DataGridViewRow r in dgvTags.SelectedRows)
{
l.Tags.Add(r.DataBoundItem as Tag);
}
This is one of those cases where there are lots and lots of ways of solving the problem. The code I've given below may not be the best but it works for getting a list of typed objects from the SelectedRows collection.
IList<Tag> myrows = dataGridView1.SelectedRows.Cast<DataGridViewRow>().Select(x => x.DataBoundItem as Tag).ToList();
This uses Linq, and is essentially the same as your method, the Linq just tidies things up a little by removing the foreach.
The problem you are having in your comment is because of no implicit converstion between the System.Collections.Generic.List<T> created by Linq and System.Data.Objects.DataClasses.EntityCollection<T>.
I believe that this should work:
Tags = new System.Data.Objects.DataClasses.EntityCollection<RS.Tag>(
dataGridView1.SelectedRows.Cast<DataGridViewRow>()
.Select(x => x.DataBoundItem as Tab).ToList());
I say believe since I've only tested with a conversion to BindingList<T> not with EntityCollection<T>.
And it turns out the EntityCollection has no way of assigning a whole list! From this question here: convert or cast a List<t> to EntityCollection<T> I came up with the following code:
dataGridView1.SelectedRows.Cast<DataGridViewRow>()
.Select(x => x.DataBoundItem as Tab).ToList().ForEach(y => Tags.Add(y));
I'd probably at this point prefer the vanilla ForEach over this oneliner.
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...
I have two objects declared as IEnumerable<DateTime> xVal and IEnumerable<double> yVal.
Then some where is my program I have:
var xVals = from p in result where p.chemical == "Benzene" select p.SampDate_Name;
var yVals = from p in result where p.chemical == "Benzene" select p.PCL;
Then I am trying to the following assignment:
xVal = xVals as IEnumerable<DateTime>;
yVal = yVals as IEnumerable<double>;
And the above code sets xVal and yVal to null.
Could anybody explain what is wrong here? I would very much appreciate the help.
Thanks.
One thing is certain: The input is not null. So xVals and yVals are non-null as debugged by me. I am also able to loop through them to get the content of each.
I will try the other suggestions when I get back and post my findings. Thanks a lot folks for your replies.
The problem here was that LINQ is executed lazy, It will be executed when you do either foreach or ToList/ToArray/ToDictionary. The two linq queries in my code were not executed before the assignment was done. Consequently xVal and yVal were set to null.
Thanks for all the help.
The as keyword will set the output to null if the input was null or the cast could not be carried out.
If you used xVal = (IEnumerable<DateTime>)xVals you would probably get an exception saying that it could not be cast.
MSDN description for as keyword
If you have a generic collection, to get it to IEnumerable, try .AsEnumerable(). So your new code...
xVal = xVals.AsEnumerable();
yVal = yVals.AsEnumerable();
The as keyword doesn't actually do a cast, but does conversions between related reference types. So if you have a concrete type, you could treat assign it to a new variable with a type of the base class using as. If the types are not compatible, then as will return null. This is a good way to do type checking without having to worry about exceptions. Instead you can perform a null check on the result of the conversion.
It's hard to tell what types p.SampDate_Name and p.PCL are, but I would guess strings? If so you can add the cast to the select statement.
var xVals = from p in result where p.chemical == "Benzene" select DateTime.Parse(p.SampDate_Name);
var yVals = from p in result where p.chemical == "Benzene" select Double.Parse(p.PCL);
I've got a problem with the following code:
public IEnumerable<ISession> GetSessions()
{
// ...
using (ProvaDbEntities DBEntities = new ProvaDbEntities(Utilities.ToEntitiesConnectionString()))
{
ObjectQuery<session> sessions = DBEntities.session;
IEnumerable<session> q1 = from session in sessions
where session.site == this.Name
select session;
List<Session> sessionList = new List<Session>();
foreach (var s in q1)
{
sessionList.Add(new Session(s.id.ToString(),s.username, s.site, new DateTime()));
}
IEnumerable<Session> res = sessionList;
return sessionList;
}
}
The exception is:
Is not possible to cast object type 'System.Collections.Generic.List`1[prova3.Session]' to type 'System.Collections.Generic.IEnumerable`1[TAP2009.AuctionSite.Interfaces.ISession]'.
Looking at this SO question it seems to be correct. Am I wrong?
It should be fine, so long as Session implements ISession - if you're using C# 4 and .NET 4. If you're not, it won't be.
Note that the question you referred to use the same "T" in both cases - whereas the exception you've got is about converting a List<Session> to an IEnumerable<ISession>. You haven't stated where you're getting the exception, which makes it a bit harder to see exactly what's going on... Are you sure this is actually the code which is failing? Are you sure you're getting an exception rather than a compile-time failure?
EDIT: If you're not using .NET 4 and C# 4, the workaround for covariance is reasonably simple here - use the Cast<T>() LINQ operator:
return sessionList.Cast<ISession>();
Have you tried using the extension method AsEnumerable()?
So this line
IEnumerable<Session> res = sessionList;
Would change to
IEnumerable<Session> res = sessionList.AsEnumerable();
The return type is public IEnumerable<ISession>, i forgot to specify the type of the Ienumerable..
You can add using System.Linq and use the extension method Cast<T> that returns a IEnumerable<T>.
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();