How can i use LINQ with property - linq

Hi I have a array list if type class "DtContract".
ArrayList listOfContracts_;
foreach (DTContract contract in listOfContracts_)
{
if (contract.Engine != DTIsland.EngineType.AMADEUS && contract.Engine !=DTIsland.EngineType.SABRE)
continue;
}
I want to do it through LINQ.
I want to filter the Contract whose EngineType == AMADEUS && EngineType == SABRE. Please suggest how can i do it through Linq and get the result in List or in array list.
I am doing this to Optimize the code.
Please Help...

var result = listOfContracts_.Where(contract=>contract.Engine != DTIsland.EngineType.AMADEUS && contract.Engine !=DTIsland.EngineType.SABRE).ToList();

your foreach loop doen't do anything meaningful, what you are trying achieve?
If you want to use linq
listOfContracts_.OfType<DTContract>()
.Where(contract => contract.Engine != DTIsland.EngineType.AMADEUS &&
contract.Engine != DTIsland.EngineType.SABRE);

Related

What is the most efficient way or best practice for null check when you use Split and FirstOrDefault methods together?

I use Split and LastOrDefault methods together, I use this code block for null check. But it does not seems the most efficient way to me. Because I use lots of check and && operators. It seem a little ugly. Is there any way to accomplish this null-check in a better way? (I searched on web but couldn' t find related answers.)
Note : C# Language version 4.0
Here is my code :
if (HttpContext.Current.Request.Url.AbsolutePath.Split('/') != null &&
HttpContext.Current.Request.Url.AbsolutePath.Split('/').Length > 0 &&
HttpContext.Current.Request.Url.AbsolutePath.Split('/').Last() != null &&
HttpContext.Current.Request.Url.AbsolutePath.Split('/').Last().Split('.') != null &&
HttpContext.Current.Request.Url.AbsolutePath.Split('/').Last().Split('.').Length > 0 &&
HttpContext.Current.Request.Url.AbsolutePath.Split('/').Last().Split('.').First() != null)
{
pageName = HttpContext.Current.Request.Url.AbsolutePath.Split('/').LastOrDefault().Split('.').FirstOrDefault();
}
Thanks for all answers.
The tests are all not needed:
First, don't run Split multiple times on the same data:
var splitSlashAbsPath = HttpContext.Current.Request.Url.AbsolutePath.Split('/');
The return array from Split can never be null
// if (splitSlashAbsPath != null &&
the return array from Split can never be zero length
// splitSlashAbsPath.Length > 0 &&
so the return from Last() can never be null
// splitSlashAbsPath.Last() != null &&
Don't run split multiple times on the same data (and calling Last on an array doesn't make sense)
var splitDotAbsPath = splitSlashAbsPath[splitSlashAbsPath.Length-1].Split('.');
the return array from Split can never be null
// splitDotAbsPath != null &&
the return array from Split can never be zero length
// splitDotAbsPath.Length > 0 &&
so, the First() from Split can never be null
// splitDotAbsPath.First() != null)
// {
since you can call Last, calling LastOrDefault makes no sense
same for FirstOrDefault
// pageName = splitDotAbsPath.FirstOrDefault();
Calling First on an array also doesn't make sense
pageName = splitDotAbsPath[0];
// }
So, in summary you have:
var splitSlashAbsPath = HttpContext.Current.Request.Url.AbsolutePath.Split('/');
var splitDotAbsPath = splitSlashAbsPath[splitSlashAbsPath.Length-1].Split('.');
pageName = splitDotAbsPath[0];
However, in general, using Split for just getting one element is very inefficient, so this would be better:
var path = HttpContext.Current.Request.Url.AbsolutePath;
var pastSlashPos = path.LastIndexOf('/') + 1;
var countUntilDot = path.IndexOf('.', pastSlashPos);
countUntilDot = (countUntilDot >= 0 ? countUntilDot : path.Length) - pastSlashPos;
pageName = path.Substring(pastSlashPos, countUntilDot);

LINQ to Entities does not recognize the method 'Char get_Chars(Int32)' method, and this method cannot be translated into a store expression

I would like to select only the records that have the field "1" from the string eventTriggers (that looks something like this : "00100010" )
I've tried and succesfully done so with more than 1 calls .. but i doubt its efficient. Basically I would want something like this ... but apprently LINQ does not support this.
(LINQ to Entities does not recognize the method 'Char get_Chars(Int32)' method, and this method cannot be translated into a store expression.)
using (var service = new dB.Business.Service.BaseBusinessService<memo>())
{
List<memo> result = service.Repository.GetQuery().Where(p => p.ID == ID && p.eventTriggers[index] == '1').ToList();
}
Any hints towards the correct solution ? Thank you !
I Had the same problem and solved It with substring.
ervice.Repository.GetQuery().Where(p => p.ID == ID && p.eventTriggers.Substring(index,1) == "1").ToList();
EF can't convert the char array operation into a valid query. How about
IEnumerable<Memo> memos
using (var service = new dB.Business.Service.BaseBusinessService<Memo>())
{
memos = service.Repository.GetQuery()
.Where(p => p.ID == ID).AsEnumerable();
}
var result = memos.Where(m => m.eventTriggers[index] == '1').ToList();
This gets all the memos with a matching ID locally then filters on the eventTriggers array.
Alternatively you could convert eventTriggers into a numeric value and use a bit mask, this would probably be a much faster query.
Linq looking like this,
using (var service = new dB.Business.Service.BaseBusinessService<Memo>())
{
result = service.Repository.GetQuery()
.Where(p =>
p.ID == ID
&&
m.eventTriggers & mask != 0).ToList();
}
more exapmles here
Solved:
using (var service = new dB.Business.Service.BaseBusinessService<memo>())
{
List<memo> result = service.Repository.GetQuery().Where(p => p.ID == ID && p.eventTriggers.Contains('1')).ToList();
}

Linq with Logic

I have simple Linq statement (using EF4)
var efCars = (from d in myentity.Cars
where d.CarName == inputCar.CarName
&& d.CarIdNumber == inputCar.IdNumber
&& d.Make == inputCar.Make
select d.Car);
I want it to be smarter so that it will only query across one or more of the 3 fields IF they have values.
I can do a test before, and then have a separate linq statement for each permutation of valyes for inputcar
(i.e. one for all 3, one for if only carname has a value, one for if carname AND CarIdNumber has a value etc etc)
but there must be a smarter way
Thanks!
If "has no value" means null then you can use the null coalescing operator ?? to say take the first value if populated, otherwise take the second:
var efCars = (from d in myentity.Cars
where d.CarName == (inputCar.CarName ?? d.CarName
&& d.CarIdNumber == (inputCar.IdNumber && d.CarIdNumber)
&& d.Make == (inputCar.Make && d.Make)
select d.Car);
This basically says if a value exists it must match, otherwise treat it as matching
However if instead you're saying "when a special value (empty string) ignore it, otherwise match" then you can do one of two approaches (or possibly more!):
where (inputCar.CarName == "" || d.CarName == inputCar.CarName)
where (string.IsNullOrEmpty(inputCar.CarName) || d.CarName == inputCar.CarName)
For performance (when dealing with database queries) it can sometimes be beneficial to let EF generate queries based on the filters, instead of using one generic query. Of course you will need to profile whether it helps you in this case (never optimize prematurely), but this is how it would look if you dynamically build your query:
var efCars =
from car in myentity.Cars
select car;
if (inputCar.CarName != null)
{
efCars =
from car in efCars
where care.CarName == inputCar.CarName
select car;
}
if (inputCar.IdNumber != null)
{
efCars =
from car in efCars
where care.CarIdNumber == inputCar.IdNumber
select car;
}
if (inputCar.Make != null)
{
efCars =
from car in efCars
where care.Make == inputCar.Make
select car;
}
where (inputCar.CarName != null || d.CarName == inputCar.CarName) &&...

If condition in LINQ Where clause

With Linq, can I use a conditional statement inside of a Where extension method?
var query = someList.Where(a => (someCondition)? a == "something" : true);
so, if 'someCondition' is false, 'Where' will be skipped.
Yes you can like:
var query = someList.Where(a => a == "something");
if (condition)
{
query = query.Where(b => b == "something else");
}
var result = query.ToList();
Because Where is producing an IQueryable, the execution is deferred until the ToList in my example so you can chain Wheres together as much as you want and then just execute it after you have passed all your conditions.
Make use of WhereIf extenstion method avaialbe in linq
Example
if (SearchControlMain.PostingID.HasValue)
query = query.Where(q => q.PostingID == SearchControlMain.PostingID);
instead of above go for the below
query = query.WhereIf(SearchControlMain.CategoryID.HasValue, q => q.CategoryID == SearchControlMain.CategoryID);
LINQ WhereIf Extension Method
LINQ to SQL Where Clause Optional Criteria
Not sure if this is appropriate but it is quite useful, you can use ifs quite handily with conditional where clauses:
var r = (from p in productinfo.tblproduct
where p.Accountid == accountid
select p);
if (uuf1 != null)
r = r.Where(p => p.UnitUserField1 == uuf1);
if (uuf2!= null)
r = r.Where(p => p.UnitUserField2 == uuf2);
So the where clause will be amended according to what is in UUF1 or UUF2 i.e. you might have only UUF1 with info, in which case it will take that and ignore the UUF2 where clause, you might have both in which it will take both or you might not have anything in UUF1 or 2 and your where clause will just take the accountid as the where clause.
In my case there were two "conditional" where depending on search keys, so I did:
var query = db.Package.Include("SomeThing")
.Where(item => searchString1 == null || searchString1 == "" || item.Contains(searchString1))
.Where(item => searchString2 == null || searchString2 == "" || item.Contains(searchString2));
...
from item in items
where condition1
&& (condition2 ? true : condition3)
select item
This is how can you can do it with the noob Linq syntax.
This applies the condition3 only if condition2 is false.
If condition2 is true, you are essentially doing && true which has no effect on the where clause.
So it is essentially doing this:
if(condition2)
{
from item in items
where condition1
select item
else
{
from item in items
where condition1
&& condition3
select item
}
I had a scenario like this where I had to check for null within the list itself. This is what I did.
items = from p in items
where p.property1 != null //Add other if conditions
select p;
// Use items the way you would use inside the if condition
But as Kelsey pointed out this would work too -
items = items.Where(a => a.property1 != null);
I'm not sure what the question is, but a possible answer could be:
Yes,
list.Where(item => { if (Foo(item)) return true; else return false; });
It would be a complicated way of saying something simple, though.
In my case, I wanted to keep the elements which met my criteria and log the ones that didn't without iterating multiple times.
var merchantsWithLocations = allMerchants.Where(m =>
{
if (m.Locations?.Any() != true)
{
_logger.Log("Merchant {merchantId} has no locations", m.Id);
return false;
}
return true;
};
Any time you want to do a side-effect per element (such as logging), breaking out the lambda into a statement body makes it easy to reason about.

Complex Expressions in a LINQ Where Clause

I was wondering if it is possible to include inner variables or delegates in linq statements?
I currently am using Linq to XML with XPath extensions and am using a where clause on an element that I cannot guarantee will exist.
Here is a sample of what I mean:
var result =
from record in xml.Root.XPathSelectElements("record")
where ...
select record;
I want the where to be something like:
where
{
var element = record.XPathSelectElement("element[#type='sometype']");
return (element != null && element.Value.Contains("keyword"));
}
You want the "let" keyword in Linq. Something like this?
var result =
from record in xml.Root.XPathSelectElements("record")
let element = record.XPathSelectElement("element[#type='sometype']")
where (element != null && element.Value.Contains("keyword"))
select record;
You could use a "let" clause here;
from record in xml.Root.XPathSelectElements("record")
let element = record.XPathSelectElement("element[#type='sometype']")
where element != null && element.Value.Contains("keyword")
select record;
I don't know the query syntax well enough to say for sure, but this would be trivial with the functional syntax:
var result = xml.Root.XPathSelectElements("record").Where(record => {
var element = record.XPathSelectElement("element[#type='sometype']");
return (element != null && element.Value.Contains("keyword"));
});

Resources