From the results of the SQL Server stored procedure 'sp_help' we get a DataSet containing a couple of tables. Seven if i am correct. One of them contains information about the constraints. Each foreign keys is documented by two consecutive rows in that table. The first row contains the constraint type, it's name and other details. It's followed by an empty row except for one column, 'constaint_keys' that contains the column names references of the constraint.
Other constraint types are described in one single row.
Any idea on how to "flatten" this information, using Linq, in a way that we can be sure that any couple made of two rows is really made of rows {n, n + 1}
Thank you for your help!
To gather elements of an IEnumerable by two :
data.Select((x, i) => new { Index = i, Value = x }).GroupBy(x => x.Index / 2)
You can use Enumerable.Range() to get the range of indexes you want to work with:
var unflattenedConstraints = constraintsTable.Rows;
var constraints = from index in Enumerable.Range(0, unflattenedConstraints.Count / 2)
.Select(x => x * 2)
let row1 = unflattenedConstraints[index]
let row2 = unflattenedConstraints[index + 1]
// Combine the rows
Related
I want to single out the rows of a table using a LINQ expression based off a certain passed value and then sum a specific column attribute of each of these rows while keeping the individual sums of the rows separate to one another.
The user enters a specific quantity value using a quantity input - this passed quantity value needs to be used in a LINQ expression to filter out the rows which meet the desired condition.
Below is a variable being assigned to the passed quantity value:
int quantitySelected;
JObject passedQuantity = JObject.Parse(data);
quantitySelected = (int)passedQuantity["qtySelect"]
"quantitySelected" is now equal to the value passed through by the user - and now, using this value in a LINQ expression, i want to be able to filter a specific table (InvoiceLine) based off the condition being met and then include all the filtered rows according to a foreign key identifier (ProductID):
var dynamicReader = DBAccessor.InvoiceLines.Where(zz => zz.Quantity >= quantitySelected).Include(yy => yy.ProductID);
The relevant extract from the database structure is as follows:
I want to have all the rows which have a quantity greater or equal to what the user inputted, stored inside the dynamic reader with reference to the ProductID to which they are associated. So for example:
I want to be able to single out the row which has a ProductID of 8 (which can be seen twice here) and then sum their quantities, (so ProductID 8 will ultimately have a sum of 6) and so forth (for each repeating ProductID).
Is there a way to accomplish this using a LINQ query expression? or will i need to use additional C#?
I want to be able to single out the row which has a ProductID of 8 (which can be seen twice here) and then sum their quantities
That is nice. Apparently you want the complete row, in the row you want the ProductId and the sum of the quantities. But what do you want to do with the other properties: do you want InvoiceLineId 7 or 10? InvoiceId 3 or 4? Or are you only interested in the sum?
My advice would be to make groups of InvoiceLines that have the same ProductId. For this you can use GroupBy. Use parameter resultSelector to select the properties that you want in your end result:
var result = DBAccessor.InvoiceLines
.Where(invoiceLine => invoiceLine.Quantity >= quantitySelected)
// group the remaining invoicelines into groups with the same productId
.GroupBy(invoiceLine => invoiceLine.ProductId,
// parameter result selector: use the common productId and all invoiceLines
// that have this productId to make one new:
(productId, invoiceLinesWithThisProductId) => new
{
ProductId = productId,
Quantity = invoiceLinesWithThisProductId
.Select(invoiceLine => invoiceLine.Quantity)
.Sum(),
... // other properties, you didn't specify what you want
});
After reading the description, you seem to be willing to merge duplicates rows into one from the list and sum up the quantity of the duplicate rows. You can use GroupBy statement to get the desired results.
Here is an example, you can further fix it accordingly to fit your needs.
var dynamiceReader = DBAccessor.InvoiceLines.Where(x=> x.Quantity >= quantitySelected).GroupBy(e => e.ProductID).Select(product =>
{
var p = product.First();
return new
{
InvoiceLineID = p.InvoiceLineID,
InvoiceID = p.InvoiceID,
ProductID = p.ProductID,
Quantity = product.Sum(sum => sum.Quantity)
};
});
Similarly, if you want to include the merged Ids as well, then you can modify it like below:
InvoiceLineID = string.Join(", ", product.Select(x => x.InvoiceLineID)),
I'm trying to select a distinct values from a DataTable using Linq. The DataTable gets populated from an excel sheet which has dynamic column apart from each excel sheet has a column name SERIAL NUMBER which is mandatory.
I have a DataTable for demo purpose which consist of 4 serial number as:
12345
12345
98765
98765
When I do
var distinctList = dt.AsEnumerable().Select(a => a).Distinct().ToList();
If I do
var distinctList = dt.AsEnumerable().Select(a => a.Field<string>("SERIAL NUMBER").Distinct().ToList();
Then I get the correct results, however but it only contains the one column from dt and not all the other columns
I get all four records instead of 2. Can someone tell me where I'm going wrong please.
The problem is that Distinct method by default uses the default equality comparer, which for DataRow is comparing by reference. To get the desired result, you can use the Distinct overload that allows you to pass IEqualityComparer<T>, and pass DataRowComparer.Default:
The DataRowComparer<TRow> class is used to compare the values of the DataRow objects and does not compare the object references.
var distinctList = dt.AsEnumerable().Distinct(DataRowComparer.Default).ToList();
For more info, see Comparing DataRows (LINQ to DataSet).
So, you want to group them by Serial Number and retrieve the full DataRow? Assuming that after grouping them we want to retrieve the first item:
var distinctList = dt.AsEnumerable().GroupBy(a => a.Field<string>("SERIAL NUMBER"))
.Select(a => a.FirstOrDefault()).Distinct().ToList();
EDIT: As requested
var distinctValues = dt.AsEnumerable().Select(a => a.Field<string>("SERIAL NUMBER")).Distinct().ToList();
var duplicateValues = dt.AsEnumerable().GroupBy(a => a.Field<string>("SERIAL NUMBER")).SelectMany(a => a.Skip(1)).Distinct().ToList();
var duplicatesRemoved = dt.AsEnumerable().Except(duplicateValues);
In ToTable method the first parameter specifies if you want Distinct records, the second specify by which column name we will make distinct.
DataTable returnVals = dt.DefaultView.ToTable(true, "ColumnNameOnWhichYouWantDistinctRecords");
Here there is no need to use linq for this task !
Using Linq a GroupBy would be better suited, by the sounds of it.
var groups = dt.AsEnumerable().GroupBy(a => a.SerialNumber).Select(_ => new {Key = _.Key, Items = _});
This will then contain groupings based on the Serial Number. With each group of items having the same serial number, but other property values different.
Try this:
List<string> distinctValues = (from row in dt.AsEnumerable() select row.Field<string>("SERIAL NUMBER")).Distinct().ToList();
However to me this also works:
List<string> distinctValues = dt.AsEnumerable().Select(row => row.Field<string>("SERIAL NUMBER")).Distinct().ToList();
My process to get first N rows
Get All Data from Database using Entity Framework
var list = new MyDbContext().Set<EntityName>();
Get First N rows using C#
var firstNRows = list.Take(N); // N = int
Suppose,
If N = 2 then I want the first 2 rows of the table but entity give me all rows of the table. Is there any way that entity give me only first N rows from the table not all data from the table?
Actually var list = new MyDbContext().Set<EntityName>(); gets no data at all, it returns a IQueryable<EntityName> which is just a representation of a query of all rows.
When you do var firstNRows = list.Take(N); that also gets no data, that also is a IQueryable<EntityName> which is a representation of a query of the first N rows in the database.
You don't actually get data from the database until you do something like a .ToList()
var firstNRowsList = firstNRows.ToList(); //The database is queried here for the first time.
var awards = await _context.Awards.AsNoTracking()
.OrderBy(x => x.Id)
.Take(15)
.ToListAsync();
How can I get an array of datatable row numbers which meet a certain criteria? For example I have a datatable with a column "DateTime". I want to retrieve the row numbers of the datatable where "DateTime" equals the variable startTime.
I know how to retrieve the actual row, but not the number of the row in the datatable.
Any help will be appreciated :)
int count = tblData.AsEnumerable()
.Count(row => row.Field<DateTime>("DateTime").Equals(startTime));
or as query:
int count = (from row in tblData.AsEnumerable()
where row.Field<DateTime>("DateTime").Equals(startTime)
select row).Count();
If I am reading the question right, using the overload of Select that allows a second input for the index may work for you. Something like
var indices =
table.AsEnumerable()
.Select((row, index) => new { row, index })
.Where(item => item.row.Field<DateTime?>("DateTime") == startTime)
.Select(item => item.index)
.ToArray();
If that date matches on the first, third, and sixth rows, the array will contain indices 0, 2, and 5. You can, of course, add 1 to each index in the query if you would like row numbers to start at 1. (ex: .Select(item => item.index + 1))
This is not possible. Note that with SQL (I assume you use SQL), the row order returned is not guaranteed. Your rows are ordered physically according to the primary key. So if you want a reliable row identifier, you must use your primary key number/id.
Using LINQ to SQL, how do I get the row with 1, 21? I'm looking for
SomeId==1
and
SecondId is a unique entry
SomeId SecondId
0 20
1 21
1 22
1 22
EDIT:
Ok, sorry. That wasn't clear. What I'm trying to do is generically find that row. There might be another entry that looks like this:
1 25
And that is the only 25. So I would get back two rows. Without referencing specific Ids, how do I find these two rows?
EDIT: Okay, it was really unclear what you meant before, but now I think I see what you mean, and you want something like:
var query = from row in table
where row.SomeId == targetId
group row by row.SecondId into g
where g.Count() == 1
select g.Single();
In other words:
Filter by SomeId first
Group by SecondId
Filter so that only groups with a single entry for that SecondId are returned
Select the sole entry from that group
There can be multiple such groups, of course - so you would get (1, 21) and (1, 25) in your example.
EDIT: If you saying you would like to find any combination of SomeId & SecondId where there are more than one row for that combination? then you could do the following:
var results = source.Where(x => x.SomeId == 1).GroupBy(x => x.SecondId).Where(g => g.Count > 1);
This will give you groups of results, and only return those that have more than one row. So in your example, you would get a group that returns 1,22...
If you are looking for the case where you only have rows in which there is a single entry in the table with that combination (the opposite of what I'm returning) you can change the comparison operator from '>' to '==' and another answer-er has also shown this possibility.