Why is LINQ query to DataTable not working? - linq

I have a DataTable, dt, that contains the following:
As you can see, there are two sets of files here: baseline (columns 1-3) and target (columns 4-6). So in this case I have 4 baseline files, m4, m5, m1, and m3 (m1 in row 5 is copied from row 3) and one target file, m1. The problem is that the information for the baseline file m1.txt is duplicated, so I'm trying to remove it using the following LINQ statement:
var extraneousRows = dt.Rows.Cast<DataRow>().
Where(
row => row["BASELINE_FOLDER"] == baselineSubfolder
&& row["BASELINE_FILE"] == baselineFilename
&& row["BASELINE_CHECKSUM"] == baselineChecksum
&& row["STATUS"] == "remove"
).ToArray();
foreach (DataRow dr in extraneousRows)
{
dt.Rows.Remove(dr);
}
This should remove the 3rd row from the DataTable but it doesn't. The code works fine if I omit the && row["STATUS"] == "remove" line, so I know it's functional. And the values for baselineSubfolder, baselineFilename, and baselineChecksum are correct, so that's not the problem.
But for some reason, when I include that line about the status column, it doesn't detect that that row is in the DataTable, even though it clearly is according to the DataSet Visualizer (photo above). So it's never entering the foreach loop and not removing the necessary files. Why???
I maybe should mention that the baseline file information (first 4 rows) are being retrieved from a database, whereas the target file fields are being generated according to user input. I don't see how it would matter where the information is coming from, though, since I'm querying the DataTable directly...
UPDATE
Ok, after following the suggestions of idipous and Jamie Keeling, I've determined that the problem had to do with the foreach loop, which was never being populated. Since this query should only ever return a single row, I eliminated the loop altogether. My revised code looks like this:
var extraneousRows = dt.Rows.Cast<DataRow>().
Where(
row => row["BASELINE_FOLDER"] == baselineSubfolder
&& row["BASELINE_FILE"] == baselineFilename
&& row["BASELINE_CHECKSUM"] == baselineChecksum
&& row["STATUS"] == "remove"
).SingleOrDefault();
dt.Rows.Remove(extraneousRows);
For whatever reason, extraneousRows remains null and that last line is generating a runtime error: IndexOutOfRangeException: The given DataRow is not in the current DataRowCollection
Why isn't this working?

It actually turns out that the problem was that I needed to cast the column values to strings. The solution was incredibly simple: just add a .ToString() after the column names and viola! The following code worked like a charm:
var extraneousRows = dt.Rows.Cast<DataRow>().
Where(
row => row["BASELINE_FOLDER"].ToString() == baselineSubfolder
&& row["BASELINE_FILE"].ToString() == baselineFilename
&& row["BASELINE_CHECKSUM"].ToString() == baselineChecksum
&& row["STATUS"].ToString() == "remove"
).SingleOrDefault();
dt.Rows.Remove(extraneousRows);
I also found a non-LINQ way to do this, by iterating through all the rows of the DataTable. It's not the most efficient, but it works:
for (int z = 0; z < dt.Rows.Count; z++)
{
if ((dt.Rows[z]["BASELINE_FOLDER"].ToString() == baselineSubfolder)
&& (dt.Rows[z]["BASELINE_FILE"].ToString() == baselineFilename)
&& (dt.Rows[z]["BASELINE_CHECKSUM"].ToString() == baselineChecksum)
&& (dt.Rows[z]["STATUS"].ToString() == "remove"))
{
dt.Rows[z].Delete();
}
}
dt.AcceptChanges();

Related

Does the second from clause in this LINQ query do anything?

I am trying to simplify a C# method that includes the following query:
var matchingDeviceKeys =
from dev in data.Elements("Key1")
where dev.Element("Key2").Element("Key3").Element("VendorID").Value == device.Vendor &&
dev.Element("Key2").Element("Key3").Element("ProductType").Value == device.ProductType &&
dev.Element("Key2").Element("Key3").Element("ProductCode").Value == device.ProductCode
from rev in dev.Element("Key2").Element("Key3").Element("Key4").Elements("MajorRev")
where rev.Attribute("Number").Value == device.MajorRevision &&
rev.Attribute("DefaultMinorRev").Value == device.MinorRevision.ToString(CultureInfo.InvariantCulture)
select dev.Element("Key6").Element("Key7").Element("Key8");
The "rev" target for the second from clause is never used in the select line, making me wonder if that entire second from clause is doing anything. If it is doing something, what is it doing?
My apologies for obfuscating the element names. I have to be careful in sharing proprietary code.

LINQ: QuerySyntaxException

I've written some complex LINQ query which I'm trying to run against NHibernate, unfortunately this causes an exception when trying to evaluate the query (call .ToList()).
Here is the code, which is supposed to retrieve Issue objects with some extra data:
var list = from i in sess.Query<Issue>()
let readFlag = (from f in i.ReadFlags
where (f.User != null && f.User.Username == request.UserName)
||
(f.Device.Name == request.MachineName)
select f).FirstOrDefault()
let isUnread = readFlag == null
let unreadCommentsCount = isUnread ? 0 : (from c in i.Comments
where c.DateCreated > readFlag.LastSeenCommentDate
select c).Count()
let statusChanged = isUnread && i.Status != readFlag.LastSeenStatus
where isUnread || unreadCommentsCount > 0 || statusChanged
select new
{
Issue = i,
ReadFlag = readFlag,
IsUnread = isUnread,
UnreadCommentsCount = unreadCommentsCount
};
i.e. - for each Issue object look for related IssueReadFlag which matches current username or machine name. if the Flag exists, it also contains the "last seen comment date", so the code calculates the number of new comments for this Issue.
Unfortunately NHibernate is not able to handle this query (Exception details).
I'm looking for the most optimal solution for this problem.
Obtaining all the Issue objects and applying the query criteria on the client-side is unacceptable for me.
trying to find out what causes the issue: It started working as I've commented out evaluation of unreadCommentsCount and statusChanged both in "select" and "where" statements. Following this lead, It seems that referencing readFlag in any of these subqueries causes the issue (after removing reference to readFlag in "let unreadCommentsCount .." and "let statusChanged.." conditions, the query doesn't throw exceptions).
Now I need a tip on how to make it functional (working as expected) again ...
Further investigating the issue I've found out that NHibernate can't handle the uncertain state of readFlag existence.
I've ended up splitting the query into two parts, first of them takes all the Issues where readFlag does not exists, the second one queries the IssueReadFlag directly, calculating the Unread Comments Count and Changed Status.
This seems to be the only solution as for now.

Linq: Handle empty table

How do you handle an empty table/NullReference in LINQ?
I have the following Linq statement in my code:
List<FeaturedTrack> features = _db.FeaturedTracks.Where(f => (f.FeatureStartDate >= DateTime.Now && f.FeatureEndDate <= DateTime.Now) ||
(f.FeatureStartDate == null && f.FeatureEndDate == null))
.ToList<FeaturedTrack>();
My table is currently empty, now I know this table won't be empty but it got me wondering about how to handle the NullReference error in case it is.
I've tried this:
int test = _db.FeaturedTracks.Count();
if (test > 0)
{
...
}
However my code breaks on the first line, so how do I check the table is empty before running the statement?

Overwrite data dropdown values in search form (multipleSearch)

I'm having a colModel entry like this:
{name:'status', index:'status', sorttype:"text", xmlmap:"STATUS", width:"90", stype: 'select', searchoptions:{sopt: ['eq','ne'], value:':all;Hold:Hold;4-Eye-Check:4-Eye-Check;Approved:Approved;Rejected:Rejected;Closed:Closed'}},
thats working fine as long as it's used in the FilterToolBar, but if I open the NavGridSearch Im running into troubles. The entry "all" is not working anymore. The query in the FilterToolBar seems to ignore my empty but the NavGridSearch doesn't.
Is there any wildcard sign which could be used instead of an empty String, which delivers all entries regardless if I search for all status entries in the FilterToolBar or the NavGridSearch?
I use the newest OpenSource jQGrid Lib(4.3.2)
Thanks in advance!
I am trying to understand the use case for a criteria of 'all'. It seems the purpose of 'all' is that you want the grid to ignore this search criteria and return all rows regardless of this value? If that is the case, why would the user even want to select this search criteria - they can just remove it and the same effect will be achieved. Or am I missing something?
Update
The grid uses function createEl : function(eltype,options,vl,autowidth, ajaxso) to create the select for the search form. Unfortunately this select always adds the all criteria to the list, even though it has a search value of "" which will not match any rows. One workaround is to modify the grid to skip select options that have an empty value. Using the source file jquery.jqGrid.src.js you can add the following code to skip the all option:
else if (sv.length > 1 && sv[0].length === 0) continue;
Here it is within the context of createEl:
if(typeof options.value === 'string') {
so = options.value.split(delim);
for(i=0; i<so.length;i++){
sv = so[i].split(sep);
if(sv.length > 2 ) {
sv[1] = $.map(sv,function(n,ii){if(ii>0) { return n;} }).join(sep);
} else if (sv.length > 1 && sv[0].length === 0) continue; // <-- Change this line
ov = document.createElement("option");
ov.setAttribute("role","option");
ov.value = sv[0]; ov.innerHTML = sv[1];
elem.appendChild(ov);
if (!msl && ($.trim(sv[0]) == $.trim(vl) || $.trim(sv[1]) == $.trim(vl))) { ov.selected ="selected"; }
if (msl && ($.inArray($.trim(sv[1]), ovm)>-1 || $.inArray($.trim(sv[0]), ovm)>-1)) {ov.selected ="selected";}
}
If you need a minified version, update the "src" version of jqGrid and then run it through the Google Closure Compiler.
I am not sure this is a general purpose change, which is why I am calling it a workaround for right now. Longer term a better solution needs to be found so jqGrid can be patched... I'll try to find some more time later to revisit this issue.
Does that help?

problem with delete when multiple columns

when deleteing this works:
orderitems.Delete(x => x.orderitem_sessionid == transkey);
however this does not work
orderitem.Delete(x => x.orderitem_sessionid == transkey
&& x.orderitem_productid == 6);
i get no errors, but nothing is deleted either, i have working code as a substitute of
var DeleteableItems = orderitems.All().where(x => x.orderitem_sessionid == transkey
&& x.orderitem_productid = 6);
foreach(var item in DeleteableItems) item.delete;
though the above works it still bugs me that this wont work with just nomal delete method, using subsonic 3.0.0.3 and mysql database
thanks
Have you tried:
orderitem.Delete(x => x.orderitem_sessionid == transkey
&& x.orderitem_productid == 6);
The last operator in your version is assignment not comparisson.
My answer concerned a typo but the comments on getting the generated SQL below some might find useful.
Kindness,
Dan

Resources