Index was out of range when expression converted to linq expression - linq

I am creating a collection of select list items from my userGroupsRepository.
I know that there are two records.
Is there something what i am doing wrong?
At first i have written following code as i thought this is a faster way to get my select list item collection, where i have "this._userGroupRepository.All" as IQueryable
my collection is:
List<SelectListItem> listItems = this._userGroupRepository.All.Select(
userGroup => new SelectListItem() {
Text = userGroup.GroupName,
Value = userGroup.UserGroupId.ToString()
}).ToList();
this implementation however results with
Index was out of range. Must be non-negative and less than the size of
the collection. Parameter name: index
and here i have my implementation of collection with rewriting it as foreach
List<SelectListItem> listItems = new List<SelectListItem>();
foreach (UserGroup userGroup in this._userGroupRepository.All)
{
listItems.Add(new SelectListItem(){
Text = userGroup.GroupName,
Value = userGroup.UserGroupId.ToString()});
}

Does it help to make an Enumerable of your Queryable?
this._userGroupRepository.All.AsEnumerable().Select(

Related

How can I but this list of database values in my SelectListItem and DropDownList?

Hi I’m trying to use the following approach to creating a list from my database then accessing them in my view. Here’s what I’ve been trying…
var rTypeList = from r in db.Rubrics where r.DepartmentID == 2 select r;
var selectedRubrics = typeList.Select(r => r.Category);
IList <String> rubricsList = selectedRubrics.ToList();
IList<SelectListItem> iliSLI = new List<SelectListItem>();
SelectListItem selectedrubrics = new SelectListItem();
selectedrubrics.Text = "Choose An Option";
selectedrubrics.Value = "1";
selectedrubrics.Selected = true;
iliSLI.Add(selectedrubrics);
ViewData["Options"] = iliSLI;
Then in my view I have: #Html.DropDownList("Options")
This gets my list started but how can I get the values from this list… IList <String> rubricsList = selectedRubrics.ToList();… and add them to my DropDown list?
You have almost figured out the difficult part of your problem.
Here is an explanation...
At the controller side, you need to have a List of SelectListItem type. I have passed this list to my ViewBag.DropDownData, here you could have passed it to your model instead, but I am trying to keep it as simple as possible. So you pass the list to a viewbag.
Controller code
var myList = new List<SelectListItem>
{
new SelectListItem {Text = "Yasser", Value = "YS"},
new SelectListItem {Text = "Vaibhav", Value = "VS"},
new SelectListItem {Text = "Ramanjit", Value = "RS"}
};
ViewBag.DropDownData = myList;
Now in the view using the #Html.DropDownListFor() method, the first argument should be a string/int (depending upon your value) declared in your model which will be later be used when data is posted back to the controller. The second parameter is the List we just prepared, in case if you are using a model then simply pass your model here instead.
Razor View
#Html.DropDownListFor(m => m.ValueSelected, ViewBag.DropDownData as List<SelectListItem>)
There that’s it. Your dropdown is ready to go :), here’s the ouput of my code:
Output
Hope this helps.

Filter SelectListItem value using some condition

I have one SelectListItem for DropDownList. I have to filter based on some condition. If I try adding the condition then its gives me an error like this (LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression). I ll be adding that code here. Please guide me to solve this.
Code
IEnumerable<SelectListItem> IssueId = (from txt in Db.Issues where txt.BibId == BibId
select new SelectListItem()
{
Text = txt.Description,
Value = txt.Id.ToString(),
Selected = true,
});
SelectList IssueIds = new SelectList(IssueId, "Value", "Text");
ViewBag.IssueId = IssueIds;
Thanks
Try this:
LINQ2EF does not know ToString() but after AsEnumerable() you'll get a local collection when ToString() is implemented.
IEnumerable<SelectListItem> IssueId =
(from txt in Db.Issues.Where(e => e.BibId == BibId).AsEnumerable()
select new SelectListItem()
{
Text = txt.Description,
Value = txt.Id.ToString(),
Selected = true
});
Linq To Sql can't generate TSQL for txt.Id.ToString()
You will need to iterate the result instead after executing the query, or cast to Enumerable as xeondev suggests.
That extension does not seem to be sorted by linq to Entities but you could just do the mapping once you have the issues, e.g.
var issues = (from issue in Db.Issues
where issue .BibId == BibId
select issue ).ToList();
IEnumerable<SelectListItem> IssueId = (from txt in issues
where txt.BibId == BibId
select new SelectListItem()
{
Text = txt.Description,
Value = txt.Id.ToString(),
Selected = true,
});

Complex foreach loop possible to shorten to linq?

I have a cluttery piece of code that I would like to shorten using Linq. It's about the part in the foreach() loop that performs an additional grouping on the result set and builds a nested Dictionary.
Is this possible using a shorter Linq syntax?
var q = from entity in this.Context.Entities
join text in this.Context.Texts on new { ObjectType = 1, ObjectId = entity.EntityId} equals new { ObjectType = text.ObjectType, ObjectId = text.ObjectId}
into texts
select new {entity, texts};
foreach (var result in q)
{
//Can this grouping be performed in the LINQ query above?
var grouped = from tx in result.texts
group tx by tx.Language
into langGroup
select new
{
langGroup.Key,
langGroup
};
//End grouping
var byLanguage = grouped.ToDictionary(x => x.Key, x => x.langGroup.ToDictionary(y => y.PropertyName, y => y.Text));
result.f.Apply(x => x.Texts = byLanguage);
}
return q.Select(x => x.entity);
Sideinfo:
What basically happens is that "texts" for every language and for every property for a certain objecttype (in this case hardcoded 1) are selected and grouped by language. A dictionary of dictionaries is created for every language and then for every property.
Entities have a property called Texts (the dictionary of dictionaries). Apply is a custom extension method which looks like this:
public static T Apply<T>(this T subject, Action<T> action)
{
action(subject);
return subject;
}
isn't this far simpler?
foreach(var entity in Context.Entities)
{
// Create the result dictionary.
entity.Texts = new Dictionary<Language,Dictionary<PropertyName,Text>>();
// loop through each text we want to classify
foreach(var text in Context.Texts.Where(t => t.ObjectType == 1
&& t.ObjectId == entity.ObjectId))
{
var language = text.Language;
var property = text.PropertyName;
// Create the sub-level dictionary, if required
if (!entity.Texts.ContainsKey(language))
entity.Texts[language] = new Dictionary<PropertyName,Text>();
entity.Texts[language][property] = text;
}
}
Sometimes good old foreach loops do the job much better.
Language, PropertyName and Text have no type in your code, so I named my types after the names...

LINQ (Dynamic): OrderBy within a GroupBy using dynamic linq?

I had the following query using normal linq and it was working great (using anonymous type),
var result = from s in Items
group s by s.StartTime into groupedItems
select new {groupedItems.Key, Items= groupedItems.OrderBy(x => x.Name) };
But using Dynamic Linq I cannot get it to order by within the groupby.
result = Items.GroupBy("StartTime", "it").OrderBy("Name");
It states the Name isn't available. It is worth noting that if I take my OrderBy off, everything works great but items inside each "Key" are not ordered.
This is a good question!
I simulated your situation by creating a class called Item.
public class Item
{
public DateTime StartTime { get; set; }
public string Name { get; set; }
}
and then created a basic list of items to do the groupby.
List<Item> Items = new List<Item>()
{
new Item() { StartTime = DateTime.Today, Name = "item2"},
new Item() { StartTime = DateTime.Today, Name = "item1"},
new Item() { StartTime = DateTime.Today.AddDays(-1), Name = "item3"},
};
Now the big difference in the 2 queries is where the order by is being performed. In the first query, when you perform groupedItems.OrderBy(x => x.Name) its being performed on a IGrouping<DateTime,Item> or a single entry as it iterates through all the groupings.
In the second query, the orderby is being performed after the fact. This means you're doing an orderby on a IEnumerable<IGrouping<DateTime,Item>> because the iterations have already happened.
Since Microsoft was nice they added something to help deal with this for expressions. This overload allows you to specify the item returned as it iterates through the collection. Here's an example of the code:
var expressionResult = Items.GroupBy(x => x.StartTime,
(key, grpItems) => new { key, Items = grpItems.OrderBy(y => y.Name) });
The second part of the GroupBy you can specify a lambda expression that takes a key and a grouping of items under that key and return an entry that you specify, which is the same as you're doing in the original query.
Hope this helps!

Why am I getting "Cannot convert lambda expression to type 'string' because it is not a delegate type"?

I have a simple table called LookupTable with two fields: Id (int) and Description (nvarchar) that I want to use to populate a drop down list.
The following code gives me the error:
IEnumerable<SelectListItem> items =
_entities.LookupTable.Select(t=> new SelectListItem {Value = t.Id,
Text = t.Description } );
I have a using System.Linq; statement already, and I get a runtime error if I try t.Id.ToString().
I must be missing something simple, right?
It is not clear from your question what is the type of _entities.LookupTable. If we suppose that it is some IQueryable<SomeModel> or IEnumerable<SomeModel> where SomeModel contains two properties Id and Description, you must ensure that you are properly converting those two values to string as the Value and Text properties of a SelectListItem are strings.
You may also try to eagerly execute the query by calling .ToString():
var items = _entities
.LookupTable
.ToList()
.Select(t => new SelectListItem
{
Value = t.Id.ToString(), // <-- notice that you might need a ToString if the Id property is integer
Text = t.Description
});

Resources