Convert Generic.List<int?> to Generic.List<int> - c#

I am returning a result set from a stored procedure. It is one temporary table that sends back a list of integers.
When I try to return the results I get an error Generic.List<int?> to Generic.List<int>
This is what I'm trying:
using (SecurityEntities ctx = new SecurityEntities())
{
List<int> newList = ctx.spStoreSearch(storeNumber).Where(x => x != null).Select(x => x).ToList();
return test;
}
under the ctx.spStoreSearch(storeNumber).Where section it says Method, Delegate or event is expected
I based what I've currently done on this answer
Could my error be in the stored procedure itself?
This is what I'm returning from the storedProc select * from #TempTable

Select the value of Nullable int like:
.Select(x => x.Value)
You can also do casting like:
.Select(x => (int) x)
Your query could be:
List<int> newList = ctx.spStoreSearch(storeNumber)
.Where(x => x.HasValue)
.Select(x => x.Value).ToList();
You are getting the exception because your element in the List is of type int? or Nullable<int> so when you do Select(x=> x) it is selecting items of type int? and you can't assign that to List<int>.

Selects all not null values and add them into a list of integers (filtered out by using value property) .
//select int list
var nullableListIds = nullableListRecords.Select(o => o.ID).ToList();
//create list
var intList = nullableListIds.Where(n => n != null).Select(n => n.Value).ToList();

You have two options, you can either convert the nullable integers you have to 0 (or any other number that you decide to choose) and include them in your list or you can filter them out...
List<int?> nullableInts = new List<int?>();
// Lets generate some data to play with...
for (int i = 0; i < 100; i++)
{
int? digit = i % 2 == 0 ? (int?)null : i;
nullableInts.Add(digit);
}
// Below we use the GetValueOrDefault method to convert all null integers to -1
List<int> ints = nullableInts.Select(x => x.GetValueOrDefault(-1)).ToList();
// Below we simply cast the nullable integer to an integer
List<int> filteredInts = nullableInts.Where(x => x.HasValue)
.Select(x => (int)x).ToList();

Related

How to put contains on DataTable Rows using LINQ

This works:
exists = dt.AsEnumerable().Where(c => c.Field<int>("GENARTNR").Equals(int.Parse(nodeID))).Count() > 0;
Now nodeID is a string which can have more than 1 nodeIdz so 100,178,111,200 or 100 or 200,100
Now I want to do something like:
exists = dt.AsEnumerable().Where(nodeID.Contains(c => c.Field<string>("GENARTNR")));
But I am getting :
Cannot convert lambda expression to type 'char' because it is not a delegate type
Any work around this or some other suggestion?
First, don't use Field<string>("GENARTNR") is it's actually an int column.
You can use this approach that uses Contains with an int[]:
int[] nodeIDs = ParseNodeId(nodeId);
exists = dt.AsEnumerable().Any(r => nodeIDs.Contains(r.Field<int>("GENARTNR")));
private static int[] ParseNodeId(string nodeId)
{
return nodeId?.Trim().Split(',')
.Select(n => int.TryParse(n.Trim(), out int id) ? id : (int?)null)
.Where(x => x.HasValue)
.Select(x => x.Value)
.ToArray() ?? Array.Empty<int>();
}

C# : Need to get Datable id column into list of string

C# : Need to get Data table id column into list of string
List<string> ids = new List<string>();
ids = dtTable.Rows.OfType<DataRow>().Select(dr => dr.Field<string>("GROUP_ID"))
.Where(dr => dr != null).ToList();
I get this error :
Unable to cast object of type 'System.Int32' to type 'System.String'.
If I change the type to int then it can't handle null values so I have give the type as string
cast column values as int? and ignore nulls
var ids = dtTable.Rows.OfType<DataRow>()
.Select(dr => dr.Field<int?>("GROUP_ID"))
.Where(i => i.HasValue)
.Select(i => i.Value)
.ToList();
you cant convert int to string.. very clear
.Where(dr => dr != null).Select(dr => dr.Field<int>("GROUP_ID").ToString())
use type as int and then use to-string to convert value to string
I assume that the column GROUP_ID is of type int. You can do two things: Convert all the values in this column to string, or create a list of int.
To create a list of int:
List<int> ids = new List<int>();
ids = dtTable.Rows
.OfType<DataRow>() // Select all rows.
.Select(dr => dr.Field<int?>("GROUP_ID")) // Select all nullable ID's.
.Where(id => id != null) // Remove all null's.
.Select(id => id.Value) // Convert all values from int? to int.
.ToList(); // Put all values in a list.
Or... to convert all values to strings:
List<string> ids = new List<string>();
ids = dtTable.Rows
.OfType<DataRow>() // Select all rows.
.Select(dr => dr.Field<int?>("GROUP_ID").ToString()) // Select all nullable ID's and turn them into strings.
.Where(id => id != null) // Remove all null's.
.ToList(); // Put all values in a list.
By the way: Reevaluate your Where(dr => dr != null). It looks like you want to verify if the row is null or not. But all rows are never null. It actually checks if the ID is null.

Linq query return 1 item instead of all

I am using the query below to grab all records that have a SubCategoryName == subCatName and i want to return all of there ProductID's as a list of ints. Problem is when my code runs it is only returning 1 int(record) instead of all. How can i make it return all of the records that have that subCatName? Its returning a count = 1 with a capacity of 4. So it is a int[4] but only the first [0] is = to a actual product ID the rest returning zero?
public List<int> GetPRodSubCats(string subCatName)
{
var _db = new ProductContext();
if (subCatName != null)
{
var query = _db.ProductSubCat
.Where(x => x.SubCategory.SubCategoryName == subCatName)
.Select(p => p.ProductID);
return query.ToList<int>();
}
return null;
}
As Daniel already has mentioned, the code should work. But maybe you are expecting that it's case-insensitive or ignores white-spaces. So this is more tolerant:
subCatName = subCatName.Trim();
List<int> productIDs = _db.ProductSubCat
.Where(x => String.Equals(x.SubCategory.SubCategoryName.Trim(), subCatName, StringComparison.OrdinalIgnoreCase))
.Select(p => p.ProductID)
.ToList();
This seems more like an expected behavior here. How do you know you don't only have 1 record that satisfies the Where predicate.
Your code is correct, however you might want to normalize your comparison.
x => x.SubCategory.SubCategoryName == subCatName
to use a specific case for instance:
x => x.SubCategory.SubCategoryName.ToLower() == subCatName.ToLower()
you might also consider a Trim.

Does LINQ work on Index?

Lets say i have an array
byte[] myarr = {1,4,3,4,1,2,1,2,4,3,1,4,2};
myarr will be of length 13 (0-12 Index) which will also be the length of int[] val.
int[] val = new int[13];
I want to check index of myarr where its value is 4 i.e. 1,3,8,11.
Then i want
val[1]++;
val[3]++;
val[8]++;
val[11]++;
One way of doing this is using for loop
for(int i=0; i<myarr.length; i++)
{
if(myarr[i] == 4)
val[i]++;
}
We can use Array.indexof but it returns the first index of that value meaning that value has to be unique and my myarr has lots of same values.
Can this be done using linq?
This is what I ended up doing in LINQ (update included):
myarr.Select((b, i) => b == 4 ? i : -1)
.Where(i => i != -1)
.ToList().ForEach(i => val[i]++);
Your non-LINQ version is obviously much more succinct and readable, so I think you should use that.
You can, but it won't be simpler. LINQ will only help you with the query part, the update part has to be done in a foo loop, but since the array contains value types you need to get indexes from your LINQ-query and not the actual values and you have won nothing.
You can use an anonymous type to store the index:
int[] newIndices = myarr.Select((i, index) => new { Index = index, Value = i })
.Where (x => x.Value == 4)
.Select(x => x.Index + 1)
.ToArray();
Edit: Finally i've understood your question ;)
myarr.Select((i, index) => new { Index = index, Value = i })
.Where(x => x.Value == 4)
.Select(x => x.Index)
.ForEach(i => myarr[i]++);

Split query into multiple queries and then join the results

I have this function below that takes a list of id's and searches the DB for the matching persons.
public IQueryable<Person> GetPersons(List<int> list)
{
return db.Persons.Where(a => list.Contains(a.person_id));
}
The reason I need to split this into four queries is because the query can't take more than 2100 comma-separated values:
The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Too many parameters were provided in this RPC request. The maximum is 2100.
How can I split the list into 4 pieces and make a query for each list. Then join the results into one list of persons?
Solved
I don't want to post it as an own answer and take cred away from #George Duckett's answer, just show the solution:
public IQueryable<Person> GetPersons(List<int> list)
{
var persons = Enumerable.Empty<Person>().AsQueryable<Person>();
var limit = 2000;
var result = list.Select((value, index) => new { Index = index, Value = value })
.GroupBy(x => x.Index / limit)
.Select(g => g.Select(x => x.Value).ToList())
.ToList();
foreach (var r in result)
{
var row = r;
persons = persons.Union(db.Persons.Where(a => row.Contains(a.person_id)));
}
return persons;
}
See this answer for splitting up your list: Divide a large IEnumerable into smaller IEnumerable of a fix amount of item
var result = list.Select((value, index) => new { Index = index, Value = value})
.GroupBy(x => x.Index / 5)
.Select(g => g.Select(x => x.Value).ToList())
.ToList();
Then do a foreach over the result (a list of lists), using the below to combine them.
See this answer for combining the results: How to combine Linq query results
I am not sure why you have a method like this. What exactly are you trying to do. Anyway you can do it with Skip and Take methods that are used for paging.
List<Person> peopleToReturn = new List<Person>();
int pageSize = 100;
var idPage = list.Skip(0).Take(pageSize).ToList();
int index = 1;
while (idPage.Count > 0)
{
peopleToReturn.AddRange(db.Persons.Where(a => idPage.Contains(a.person_id)).ToList());
idPage = list.Skip(index++ * pageSize).Take(pageSize).ToList();
}

Categories

Resources