Linq on a null value - linq

I am trying to get value of dcs.Agent.AgentAlive (boolean) but I am unable to do so, can someone suggest way around. I think dcs.Agent.AgentAlive is null in some cases..
var dc = (from dcs in DataCollectionStatuses
select new {
dcs.Frequency, ha= dcs.Agent??dcs.Agent
}).FirstOrDefault();
Constructing or initializing instances of the type <>f__AnonymousType12 System.String,System.Nullable1[System.Int32],DynamicOps.ManagementModel.Agent] with the expression (dcs.Agent ?? dcs.Agent) is not supported.

You just want to know if the agent is alive correct?
If agent is null i assume he isn't.
Then you just need the very usefull Ternary Operator ?:
var dc = (from dcs in DataCollectionStatuses
select new {
dcs.Frequency,
IsAgentAlive = dcs.Agent!=null ? dcs.Agent.AgentAlive:false
}
).FirstOrDefault();
for more info
http://msdn.microsoft.com/en-us/library/ty67wk28.aspx

Related

Filter a generic list based on a reflected value of its entries with linq

I have a generic list of objects from which I want to whittle down based on a reflected value within it
List<MyCaseObj> CasesInGroup = ....;
PropertyInfo piItem = typeof(MyCaseObj).GetProperty(SomePropertyName).PropertyType.GetProperty(SomeValueMemberName);
var CasesToProcess = (from csh in CasesInGroup
where ((Guid)piItem.GetValue(piField.GetValue(csh, null), null))
.In(fld.Items.Select(i => i.ItemID))
select csh);
however it transpires that the particular value may sometimes be null, and the In extension is not to fond of that throwing a 'Non-static method requires a target.' exception
adding a && (Guid)piItem.GetValue(piField.GetValue(csh, null), null) != null doesn't work, and does the reflection twice anyway which doesnt seem right in the first place even if it did..
could someone explain how to get around this, or maybe just a nicer way to do this in the first place.
any help, pointers or such would be gratefully recieved
thanks
You could replace
(Guid)piItem.GetValue(piField.GetValue(csh, null), null))
with
(csh != null ? (Guid)piItem.GetValue(piField.GetValue(csh, null), null)) : Guid.Empty)
which should work unless Items sometimes contains Guid.Empty.
P.S. If you are up for learning something very, very cool, convert this expression to a lambda:
var myCaseType = typeof(MyCaseObj);
var param = Expression.Parameter(myCaseType);
var cond = Expression.Condition(
Expression.NotEqual(param, Expression.Constant(null, myCaseType))
, Expression.Property(param, "SomePropertyName")
, Expression.Constant(Guid.Empty)
);
var lambda = (Func<MyCaseObj,Guid>)Expression.Lambda(cond, param).Compile();
You can now re-write your select like this:
var CasesToProcess = (from csh in CasesInGroup
where lambda(csh)In(fld.Items.Select(i => i.ItemID))
select csh);

TargetInvocationException thrown when attempting FirstOrDefault on IEnumerable

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.

Linq error - "NotSupportedException: Unsupported overload used for query operator 'Select'"

I have the following Linq query:
var tmp =
from container in Container
join containerType in ContainerType on container.ContainerType equals containerType
where containerType.ContainerTypeID == 2
select new { ContainerID = container.ContainerID, TypeID = container.ContainerTypeID};
var results = tmp.Select((row, index) => new { row.ContainerID, row.TypeID, ContainerIndex = index })
As is, this works fine. If I add the following, so I can see the results in LinqPad, I get the error described in the title of this message:
results.Dump();
This error is not a LinqPad error, it's coming from Linq, and I don't understand what it means.
Thank you.
Okay, I hadn't realised Container was a LINQ to SQL data source to start with. Basically it's failing to convert the second projection to SQL.
So, you want to do just that bit in .NET instead - you can force it to use Enumerable.Select with AsEnumerable:
var results = tmp.AsEnumerable()
.Select((row, index) => new { row.ContainerID, row.TypeID,
ContainerIndex = index });

LINQ to dataset: CopyToDataTable()

I want to query a datatable (dt) and load a 2nd dt with the resultant collection of datarows. Fine - we have the CopyToDataTable() extn mthd for exactly that purpose. However it is constrained to enumerate only over DataRows, which means that I cannot return anything else e.g. a collection of anonymous types. So - how can I modify the values in the datarows?
Eg I have a dt with 3 columns: MyPK, VARCHAR01, VARCHAR02.
Foreach row, if VARCHAR01 or VARCHAR02 has the value "" (i.e. String.Empty) I want to replace that with NULL (which the underlying type allows).
I would do this as follows:
var MyCleanedDatarows =
from o in ds.Tables["dt"].AsEnumerable()
select new {
MyPK = o.Field<string>("MyPK"),
VARCHAR01 = (o.Field<string?>("VARCHAR01") == "" ? NULL : o.Field<string?>("VARCHAR01") ),
VARCHAR02 = (o.Field<string?>("VARCHAR02") == "" ? NULL : o.Field<string?>("VARCHAR02") )
};
...but then I cant use CopyToDataTable() to get back to a dt. I'm thinking I need to modify the datarows before invoking select operator, but I dont know how to achieve that. Any help/thoughts would be v.greatfully recieved.
Thanks in advance,
Tamim.
Take a look at this approach, in MSDN documentation.
http://msdn.microsoft.com/en-us/library/bb669096.aspx

Linq to SQL: .FirstOrDefault() not applicable to select new { ... }

I just asked this question. Which lead me to a new question :)
Up until this point, I have used the following pattern of selecting stuff with Linq to SQL, with the purpose of being able to handle 0 "rows" returned by the query:
var person = (from p in [DataContextObject].Persons
where p.PersonsID == 1
select new p).FirstOrDefault();
if (person == null)
{
// handle 0 "rows" returned.
}
But I can't use FirstOrDefault() when I do:
var person = from p in [DataContextObject].Persons
where p.PersonsID == 1
select new { p.PersonsID, p.PersonsAdress, p.PersonsZipcode };
// Under the hood, this pattern generates a query which selects specific
// columns which will be faster than selecting all columns as the above
// snippet of code does. This results in a performance-boost on large tables.
How do I check for 0 "rows" returned by the query, using the second pattern?
UPDATE:
I think my build fails because I am trying to assign the result of the query to a variable (this._user) declared with the type of [DataContext].User.
this._user = (from u in [DataContextObject].Users
where u.UsersID == [Int32]
select new { u.UsersID }).FirstOrDefault();
Compilation error: Cannot implicitly convert type "AnonymousType#1" to "[DataContext].User".
Any thoughts on how I can get around this? Would I have to make my own object?
Why can you keep doing the samething? Is it giving you an error?
var person = (from p in [DataContextObject].Persons
where p.PersonsID == 1
select new { p.PersonsID, p.PersonsAdress, p.PersonsZipcode }).FirstOrDefault();
if (person == null) {
// handle 0 "rows" returned.
}
It is still a reference object just like you actual object, it is just anonymous so you don't know the actual type before the code is compiled.
Update:
I see now what you were actually asking! Sorry, my answer no longer applies. I thought you were not getting a null value when it was empty. The accepted response is correct, if you want to use the object out of scope, you need to create a new type and just use New MyType(...). I know DevEx's RefactorPro has a refactoring for this, and I think resharper does as well.
Call .FirstOrDefault(null) like this:
string[] names = { "jim", "jane", "joe", "john", "jeremy", "jebus" };
var person = (
from p in names where p.StartsWith("notpresent") select
new { Name=p, FirstLetter=p.Substring(0,1) }
)
.DefaultIfEmpty(null)
.FirstOrDefault();
MessageBox.Show(person==null?"person was null":person.Name + "/" + person.FirstLetter);
That does the trick for me.
Regarding your UPDATE: you have to either create your own type, change this._user to be int, or select the whole object, not only specific columns.
if (person.Any()) /* ... */;
OR
if (person.Count() == 0) /* ... */;
You can still use FirstOrDefault. Just have
var PersonFields = (...).FirstOrDefault()
PersonFields will be be null or an object with those properties you created.

Resources