TargetInvocationException thrown when attempting FirstOrDefault on IEnumerable - linq

I suspect I'm missing something rather basic, yet I can't figure this one out.
I'm running a simple linq query -
var result = from UserLine u in context.Users
where u.PartitionKey == provider.Value && u.RowKey == id.Value
select u;
UserLine user = null;
try
{
user = result.FirstOrDefault();
}
For some reason this produces a TargetInvocationException with an inner exception of NullReferenceException.
This happens when the linq query produces no results, but I was under the impression that FirstOrDefault would return Default<T> rather than throw an exception?
I don't know if it matters, but the UserLine class inherits from Microsoft.WindowsAzure.StorageClient.TableServiceEntity

there are two possible reasons:
provider.Value
id.Value
Are you sure that theese nullables have value. You might want to check HasValue before
var result = from UserLine u in context.Users
where (provider.HasValue && u.PartitionKey == provider.Value)
&& (id.HasValue && u.RowKey == id.Value)
select u;
UserLine user = null;
try
{
user = result.FirstOrDefault();
}

I thought it produced a different error, but based on the situation in which the problem is occurring you might want to look to check if context.IgnoreResourceNotFoundException is set to false? If it is try setting it to true.
This property is a flag to indicate whether you want the storage library to throw and error when you use both PartitionKey and RowKey in a query and no result is found (it makes sense when you think about what the underlying REST API is doing, but it's a little confusing when you're using LINQ)

I figured it out - the problem occured when either id or provider had '/' in the value, which the id did. when I removed it the code ran fine
Understanding the Table Service Data Model has a section on 'Characters Disallowed in Key Fields' -
The following characters are not allowed in values for the
PartitionKey and RowKey properties:
The forward slash (/) character
The backslash () character
The number sign (#) character
The question mark (?) character

Here's some fun try putting the where query the other way around like this to see if it works (I heard a while ago it does!):
where (id.HasValue && u.RowKey == id.Value) && (provider.HasValue && u.PartitionKey == provider.Value)
Other than this you can now set IgnoreResourceNotFoundException = true in the TableServiceContext to receive null when an entity is not found instead of the error.
It's a crazy Azure storage thing.

Related

Linq where clause invalid

var advocacy = (from c in svcContext.CreateQuery("lead")
join a in svcContext.CreateQuery("product")
on c["transactioncurrencyid"] equals a["transactioncurrencyid"]
where a["capg_billingtimeframe"].Equals(126350000)
select new
{
dues = c["capg_calculatedduesbilling"],
product = c["capg_primaryproduct"],
listprice = a["price"],
eligibility = c.FormattedValues["capg_eligibility"]
});
That is my linq query and it is giving me the error: Invalid 'where' condition. An entity member is invoking an invalid property or method.
I have looked online everywhere and done their suggestions. I am not using Xrm.cs because late binding can be faster. I have tried using the == operand and I have tried doing (int) and Convert.ToInt32(a["capg_billingtimeframe"]) and even converting everything to a string. I will say that a["capg_billingtimeframe"] I know is an object (that's why I did those conversions.
I'm guessing by that integer that capg_billingtimeframe is an optionset. If it is, you need to cast it like this:
where ((OptionSetValue)a["capg_billingtimeframe"]).Value == 126350000
I used early bound and for getting the local I wrote:
OptionSetValue branch = this.InputTargetEntity.Attributes.Contains("capg_calculatorutilized") ? (OptionSetValue)this.InputTargetEntity["capg_calculatorutilized"] : (OptionSetValue)this.TargetPreImage["capg_calculatorutilized"];
I then had to get the Optionsets.cs using crmsvcutil and writing:
if (branch.Value == (int)capg_calculatorrequired.SectionA)
Works like a charm.

Queries with local collections are not supported LINQ

everyone! I'm trying to do a rather simple LINQ query to find available rooms in a hotel. (That is, find a available room from a pool of rooms, and check that there are no pending cleaning etc in the room).
But when I try to execute the third query, I get the exception you see in the title. I don't actually get the exception when I execute it, but when I try to use the "unfinishedTasksInPool" variable.
I tried turning the "unfinishedTasksInPool" into a list, too see if that would help, but whenever I try to use "unfinishedTasksInPool", I get the exception.
EDIT : Whenever I exclude "availableRoomsFromPool.Contains(tasks.roomId" in the where clause in the third query, everything seems to work normally. But that doesn't exactly solve the problem tho.
var pendingReservation = database.Reservations.Where(res => res.reservationID == resId).First();
var reservationsInSameGroup = from otherReservations in database.GetTable<Reservation>()
where (otherReservations.beds == pendingReservation.beds
&& otherReservations.rank == pendingReservation.rank
&& otherReservations.roomID != null)
select otherReservations.roomID;
var availableRoomsFromPool = from rooms in database.GetTable<Room>()
where (!reservationsInSameGroup.Contains(rooms.roomId)
&& rooms.beds == pendingReservation.beds
&& rooms.roomRank == pendingReservation.rank)
select rooms.roomId;
var unfinishedTasksInPool = from tasks in database.GetTable<HotelTask>()
where (availableRoomsFromPool.Contains(tasks.roomId)
&& tasks.taskStatus < 2)
select tasks.roomId;
It's a LINQ-to-SQL restriction. You can use local sequences in queries (as long as you use them in Contains), but you can't use a local sequence that itself is the result of a query using another local sequence.
So it's alright to do...
var availableRoomsFromPool = (from ....).ToArray();
...because the query contains one local sequence (reservationsInSameGroup).
But...
var unfinishedTasksInPool = (from ...).ToArray();
...throws the exception.
The solution is to use the result of var availableRoomsFromPool = (from ....).ToArray(); in the third query, because that reduces availableRoomsFromPool to one local sequence.

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.

Match on 2 values

I'm trying to figure out how to modify this to match on 2:
var result = _context.FirstOrDefault(c => c.CarId == carId);
I'm not sure how to tack this on. I just want to base it on c.CarId == carId && c.UserId == userId
where carId and userId are incoming params to my method that this LINQ statement resides in. I want to keep this as a lambda expression syntax.
Just do it exactly as you've written it:
var result = _context.FirstOrDefault(c => c.CarId == carId && c.UserId == userId);
There's nothing wrong with that. The lambda expression isn't restricted to compare a single property.
If you want to learn about LINQ in more detail, I'd start with LINQ to Objects, which is simpler to understand and predict. There are various tutorials around for it, and I have a blog series called Edulinq which examines each operator in detail.

LINQ Dynamic Expression API, predicate with DBNull.Value comparison

I have an issue using the Dynamic Expression API. I cannot seem to compare a DataTable field against DBNull.Value. The API is supposed to be able to "support static field or static property access. Any public field or property can be accessed.". However given the following query:
var whatever = table1.AsEnumerable()
.Join(table2.AsEnumerable(),
(x) => x.Field<int>("Table1_ID"),
(y) => y.Field<int>("Table2_ID"),
(x, y) => new { x, y})
.AsQueryable()
.Where("x[\"NullableIntColumnName\"] == DBNull.Value");
I end up getting the error: "No property or field 'DBNull' exists in type '<>f__AnonymousType0`2'"
Anyone have ideas on how to get around this? I can't use Submission.Field("NullableIntColumnName") in the string passed to the Where method either, btw, or else I would be able to compare against null instead of DBNull.Value.
Well, I finally got it. cptScarlet almost had it.
var values = new object[] { DBNull.Value };
...
.Where("x[\"NullableIntColumnName\"] == #0", values);
or
.Where("x[\"NullableIntColumnName\"] == #0", DBNull.Value);
What happens when you replace your current .Where with something like
.Where(string.format("x[\"NullableIntColumnName\"] == {0}",DBNull.Value));
If you change x.Field<int>("Table1_ID") to x.Field<int?>("Table1_ID") then you'll get nullable integers instead of regular integers, and any DBNull values will be converted to simple C# null values. Based simply on your code snippet, I'm not even sure you'd need dynamic expressions - a simple .Where(foo => foo.x == null) ought to work.
In general, you can also try:
.Where("NullableColumnName.HasValue");
Sorry to non-answer with a USL but...
Have you looked in the source? There's not a lot of it. My guess is that DBNull is not in the list of registered root objects.
I dont have the source to hand right now, but it is also likely to tell you what any other constants one might compare against might be.
.Where(a => a.IntColName == null);
Edit:
Sorry, I did't see this dynamic requirement... Dynamic would be: (at least in Framework 4)
var intColName = "...";
.Where(string.Format("it.{0} is null", intColName));

Resources