var x = new {
Name = "qwe",
Options = someList.Select(x=>x.KEY).Select(x =>
new {
Title: someOtherList.FirstOrDefault(y => y.KEY == x) != null ?
someOtherList.FirstOrDefault(y => y.KEY == x).Title :
null
}
)
}).ToList();
I'm making a serializeable list of objects. Please have a look on how i fetch the Title property for each option.
My problem is that I'm fetching more properties than the title, and the conditional operator feels quite excessive for each property.
Is there any "better" way of writing this?
A simple solution would be to use the following:
Title= someOtherList.Where(y => y.KEY == x).Select(x => x.Title).FirstOrDefault()
That is doing the following:
From someOtherList, return those elements with Key equal to x.
From those elements, select the Title.
Return the first title - or null if there are none.
Canonically, the approach most similar to the original code is to use a statement lambda.
Options = someList.Select(x=>x.KEY).Select(x =>
{
var other = someOtherList.FirstOrDefault(y => y.KEY == x);
return new {
Title = other == null ? null : other.Title
};
})
You can call a method instead:
Options = someList.Select(x=>x.KEY).Select(x => CreateObject(x, someOtherList));
public YourObject(or dynamic) CreateObject(YourObject x, List<SomeOtherObject> someOtherList)
{
var other = someOtherList.FirstOrDefault(y => y.KEY == x);
return new
{
Title = (other == null ? null : other.Title),
Foo = (other == null ? null : other.Foo),
...
}
}
Or accomplish the same with the let keyword in a Linq query expression as #DarinDimitrov displays.
Related
I've got a method which can accept an optional int? value as a number of items to Take from a collection. I want to return all items if a null value is passed. Right now I have to duplicate my query to accomplish this
if(take == null)
{
x = db.WalkingDeadEps.Where(x => x.BicyclesCouldHaveSavedLives == true).ToList()
}
else
{
x = db.WalkingDeadEps.Where(x => x.BicyclesCouldHaveSavedLives == true).Take(take).ToList()
}
Is there a simpler way? Something like this?
.Take(take != null ? take : "all")
with Linq you have the option to store your query in variables. it will not be executed until you call ToList or equivalent methods on it.
var query = db.WalkingDeadEps.Where(x => x.BicyclesCouldHaveSavedLives == true);
x = take.HasValue ? query.Take(take.Value).ToList() : query.ToList();
I am just trying to concatenate a string on to a column returned from the database like so:
var aaData =
(from pr in ctx.PaymentRates
where pr.ServiceRateCodeId == new Guid("BBCE42CB-56E3-4848-B396-4656CCE3CE96")
select new
{
Id = pr.Id,
Rate = pr.YearOneRate + "helloWorld"
})
.ToList();
It gives me this error:
Unable to cast the type 'System.Nullable`1' to type 'System.Object'.
LINQ to Entities only supports casting EDM primitive or enumeration
types.
So, then I tried this:
var aaData =
(from pr in ctx.PaymentRates
where pr.ServiceRateCodeId == new Guid("BBCE42CB-56E3-4848-B396-4656CCE3CE96")
select new
{
pr = pr
})
.AsEnumerable()
.Select(x => new
{
Id = x.pr.Id,
Rate = x.pr.YearOneRate + "helloWorld"
})
.ToList();
But, now it gives me this error:
Object reference not set to an instance of an object.
On this line:
.Select(x => new
How can I concatenate these strings in LINQ?
The quick solution
Regarding your second code chunk I need to point out to you that you're actually doing two left outer joins on the Countries table/set, one for homeC and one for hostC.
That means that you are willing to accept null values for those two variables.
In other words, since they can be null you are somehow allowing this right here to crash with NullReferenceException, should those variables turn out to be null:
.Select(x => new
{
Id = x.pr.Id,
HomeCountry = x.homeC.Name,
HostCountry = x.hostC.Name,
Rate = x.pr.YearOneRate + "helloWorld"
})
The error (NullReferenceException or as you saw it's message: "Object reference not set to an instance of an object.") is not here
.Select(x =>
but rather here
x.homeC.Name and x.hostC.Name
where you will most certainly dereference a null reference.
That's just Visual Studio's way of pointing out the best statement that fits around the error.
So, the quickest solution would be to do this:
.Select(x => new
{
Id = x.pr.Id,
HomeCountry = (x.homeC != null) ? x.homeC.Name : "HomeCountry not found",
HostCountry = (x.hostC.Name != null) ? x.hostC.Name : "HostCountry not found",
Rate = x.pr.YearOneRate + "helloWorld"
})
Notice the modification which ensures that you will still be able to extract some information from result set records for which homeC and hostC are null.
EDIT
Regarding the first query you posted:
var aaData =
(from pr in ctx.PaymentRates
where pr.ServiceRateCodeId == new Guid("BBCE42CB-56E3-4848-B396-4656CCE3CE96")
select new
{
Id = pr.Id,
Rate = pr.YearOneRate + "helloWorld"
})
.ToList();
my guess is that your 'YearOnRate' property is of type 'Nullable< of something >" (maybe decimal -- so for instance it is maybe a decimal? YearOnRate { get; set; }) and the corresponding column in the database is a nullable one.
If that is the case, then I think (in this first version of your endeavour) you could try to do this:
Rate = (pr.YearOnRate != null) ? pr.YearOneRate.Value + "helloWorld" : "[null]helloWorld"
and get away with it.
My guess is that either x.homeC, x.hostC, or x.pr are null. If you're fine using AsEnumerable to convert to Linq-to-Objects then you could just change your projection to
.Select(x => new
{
Id = (x.pr.HasValue ? x.pr.Id : 0),
HomeCountry = (x.homeC.HasValue ? x.homeC.Name : null),
HostCountry = (x.hostC.HasValue ? x.hostC.Name : null),
Rate = (x.pr.HasValue ? x.pr.YearOneRate : null) + "helloWorld"
})
My problem was, I wasn't using .AsEnumerable() properly. The code below works:
var aaData =
(from pr in ctx.PaymentRates
from homeC in ctx.Countries.Where(x => x.Id == pr.HomeCountryId).DefaultIfEmpty()
from hostC in ctx.Countries.Where(x => x.Id == pr.HostCountryId).DefaultIfEmpty()
from curr in ctx.Currencies.Where(x => x.Id == pr.YearOneCurrencyId).DefaultIfEmpty()
where pr.ServiceRateCodeId.Value.Equals(new Guid("BBCE42CB-56E3-4848-B396-4656CCE3CE96"))
select new { pr, homeC, hostC, curr })
.AsEnumerable()
.Select(x => new
{
Id = (string)(x.pr.Id.ToString() + "test"),
HomeCountry = (x.homeC != null ? x.homeC.Name : ""),
HostCountry = (x.hostC != null ? x.hostC.Name : ""),
Rate = (x.pr.YearOneRate ?? 0) + " (" + x.curr.Code + ")"
})
.ToList();
You have used DefaultIfEmpty on both homeC and hostC so you can get a null reference when you call homeC.Name or hostC.Name
Try using HomeCountry = homeC == null ? null : homeC.Name instead
If pr.YearOneRate is not a string and you want the concatenation done by the database engine you need to tell Linq-to-Entities to generate sql to convert it. If you are using Sql Server you can use this:
SqlFunctions.StringConvert(pr.YearOneRate) + "helloWorld"
If you don't need the concatenation done in the database then you can use AsEnumerable() before the Select so that you are running Linq-To-Objects
I have a scenario that I am getting the result properly .But i have to search it in that result.Here is my code.
if(productSearch.Keyword !=null || productSearch.Code!=null)
{
var key = productSearch.Keyword;
var cod = productSearch.Code;
if (productSearch.Code != null)
{
var Selected_Result = result.Results.Where(s => s.Code.ToLower().Contains(cod.ToLower())).ToList();
result.Results = Selected_Result;
}
else
{
var Selected_Result = result.Results.Where(s => s.Keyword.ToLower().Contains(key.ToLower())).ToList();
result.Results = Selected_Result;
}
}
But it gives following exception :
Object reference not set to an instance of an object on result.Results.Where(s => s.Code.ToLower().Contains(cod.ToLower())).ToList();
I know s => s.Code.ToLower() is coming NULL, but i dont know why, result has records.
Thanks in advance.
If it's null in the query then chances are it's null in the DB. To be on the safe side you can use the null coalescing operator to make sure you have at least something to call ToLower on e.g.
result.Results.Where(s => (s.Code ?? "").ToLower().Contains(cod.ToLower()))
.ToList();
I am using Linq to filter some things and some times I need to use reflection to get the value. Here is the example:
//...
PropertyType[] properties = myType.GetProperties();
var filtered = properties.Where(p=>p.PropertyType==typeof(MyMetaData)
&& ((MyType)p.GetValue(obj)).Name=="name"
&& ((MyType)p.GetValue(obj)).Length==10
).ToList();
//...
In my example I am using GetValue() method more than one time. Is there way if I can use variable to store it? I think that will help with performance.
It looks like that to include some variable in a LINQ we have to use the expression query, not method query, like this:
var filtered = (from x in properties
let a = (x.PropertyType is MyType) ? (MyType) x.GetValue(obj) : null
where a != null && a.Name == "name" && a.Length == 10).ToList();
I think this also works for method query with some Select:
var filtered = properties.Select(p=> new {p, a = (p.PropertyType is MyType) ? (MyType) p.GetValue(obj) : null})
.Where(x=>x.a != null && x.a.Name == "name" && x.a.Length == 10)
.Select(x=>x.p).ToList();
Something like following should work with method expression(lambda syntax)
var filtered = properties.Where(p =>
{
if(!p.PropertyType is MyMetaData)
{
return false;
}
var item = (MyType) p.GetValue(obj);
return item.Name == "name"
&& item.Length == 10
}
).ToList();
I have an list of objects that contains another object in it.
List<MyClass> myClass = new List<MyClass>();
I want to do some linq like this
myClass.Where(x => x.MyOtherObject.Name = "Name").ToList();
Thing is sometimes "MyOtherObject" is null. How do I check for this?
Simple, just add an AND clause to check if it's not null:
myClass.Where(x => x.MyOtherObject != null && x.MyOtherObject.Name = "Name").ToList();
As of C# 6, you can also use a null conditional operator ?.:
myClass.Where(x => x.MyOtherObject?.Name == "Name").ToList();
This will essentially resolve the Name property to null if MyOtherObject is null, which will fail the comparison with "Name".
Try it online
You can just make your predicate check for null...
myClass.Where(x => (x.MyOtherObject == null) ? false : x.MyOtherObject.Name == "Name").ToList();
I would do something like this:
myClass.Where(x => x.MyOtherObject != null)
.Where(y => y.MyOtherObject.Name = "Name")
.ToList();