Linq if-elseif-else using linq query in asp.net - c#

In my asp.net application i am using linq. I need a help what is the syntax for if-elseif-else using linq in single line.
genericReportList =
(from CD in list
select new GENERICREPORT
{
CITATIONNO = CD.CITATIONNO,
DATE = CD.DATE,
LOCATION = CD.LOCATION,
//STATUS = CD.STATUS,
PLATENO = Utilities.DecryptData(CD.PLATENO),
PSOURCE = CD.PSOURCE,
MAKE = CD.MAKE,
ID = Utilities.DecryptData(CD.ID),
NATIONALITY = CD.NATIONALITY,
SOURCE = CD.SOURCE,
NAME = Utilities.DecryptData(CD.NAME),
VIOLATION = CD.VIOLATION,
STATUS = CD.STATUS == short.Parse("1") ? "Complete" : "Incomplete"
}).ToList();
If STATUS = CD.STATUS == short.Parse("1") ? "Complete" : and 2 for "Incomplete" and 3 for "Void"

I don't understand why you are doing short.Parse("1"). This will always be 1. If you want multiple if-else in a one-liner, combine ternary operators:
STATUS = CD.STATUS == 1 ? "Complete" : CD.STATUS == 2 ? "Incomplete" : "Void"
If this is going to be used in the context of Entity Framework (or other ORM with IQueryable support), it will translate to a CASE WHEN SQL statement.

What I understand from your question if I'm not wrong, is that you might be asking about where clause.
if yes then you can always use multiple where in your query.
example :
Collection.Where(x => x.Age == 10)
.Where(x => x.Name == "Fido")
.Where(x => x.Fat == true)
more about LINQ query
http://msdn.microsoft.com/en-us/library/gg509017.aspx

You can just continue with what you already have.
STATUS = CD.STATUS == 1 ? "Complete" : (CD.STATUS == 2 ? "Incomplete" : "InProgress")

There nothing wrong with writing your own method and using it in a LINQ query. It will be far more understandable and readable than a long conditional operator.
Consider using something like:
private String GetStatus(int value)
{
if (value == 1)
return "Complete";
if (value == 2)
return "Incomplete";
if (value == 3)
return "Void";
}
Then you would call it like:
STATUS = GetStatus(CD.STATUS)

Related

Linq Query using navigation properties and Where clause

I am trying to compose a linq query using navigation properties. I am selecting properties from 3 entities:
Lockers
SectionColumn
Contracts
I require ALL rows from the Lockers table where all the following conditions are met: the LockerTypeId = "308", .OutOfOrder != true, x.SectionColumn.SectionId == "52").
The query below without the condition x.SectionColumn.SectionId == "52" works and returns exactly what I require except rows with Section id of any value are returned as I would expect.
from l in Lockers.Where(x => x.LockerTypeId == "308" && x.OutOfOrder !=
true).DefaultIfEmpty()
select new
{
ColumnNumber = l.ColumnNumber,
LockerTypeId = l.LockerTypeId,
OutOfOrder = l.OutOfOrder,
Rented = l.Contracts.Select(x => x.Contract_ID < 0 ?
false : true).FirstOrDefault(),
Section = l.SectionColumn.SectionId
}
When I add the condition 'x.SectionColumn.SectionId == "52"' as below I get the error "The cast to value type 'System.Int32' failed because the materialized value is null". Either the result type's generic parameter or the query must use a nullable type" in linqpad. SectionId is a string (varchar in SQL Server).
from l in Lockers.Where(x => x.LockerTypeId == "308" && x.OutOfOrder !=
true).DefaultIfEmpty()
I would be grateful for assistance in correctly writing this query.
First off, your code might be a little more straight forward if you stick to pure LINQ. In that case, your code should look something like the following.
var results = from l in Lockers
where l.LockerTypeId == "308" && l.OutOfOrder != true && l.SectionColumn.SectionId == "52"
select new
{
ColumnNumber = l.ColumnNumber,
LockerTypeId = l.LockerTypeId,
OutOfOrder = l.OutOfOrder,
Rented = l.Contracts.Select(x => x.Contract_ID < 0 ? false : true).FirstOrDefault(),
Section = l.SectionColumn.SectionId
}
If l.SectionColumn.SectionId represents valid navigational properties and is of type string, then this should work correctly.
You really haven't done a thorough job of describing the issue (and it looks like you didn't stick around to field questions), but if l.SectionColumn is nullable, you should be able to update your code to something like this.
var results = from l in Lockers
let sectionId = (l.SectionColumn != null) ? l.SectionColumn.SectionId : null
where l.LockerTypeId == "308" && l.OutOfOrder != true && sectionId == "52"
select new
{
ColumnNumber = l.ColumnNumber,
LockerTypeId = l.LockerTypeId,
OutOfOrder = l.OutOfOrder,
Rented = l.Contracts.Select(x => x.Contract_ID < 0 ? false : true).FirstOrDefault(),
Section = l.SectionColumn.SectionId
}

How to perform LINQ query to reach the same result of the following T-SQL query?

I have this SQL query, which works fine for my purposes :
SELECT [Documenti].[ID]
,[Documenti].[Data]
,[Documenti].[Descrizione]
,[Documenti].[DAL]
,[Documenti].[AL]
,[Documenti].[Stato]
,[Documenti].[NomeDoc]
,[Documenti].[Classe]
,[Documenti].[CTipo]
,[Documenti].[CSTIpo]
,[Documenti].[SiglaRed]
,[Documenti].[Stipula]
,[Documenti].[DataCmp]
,[Documenti].[Regione]
,[Documenti].[NumDoc]
,[Documenti].[Destinazione]
,[Documenti].[DataStampa]
,[Documenti].[Ext]
,[Tipi].GRP2
FROM [Documenti]
LEFT JOIN Tipi ON Tipi.C = [Documenti].Classe AND Tipi.C_Tipo = [Documenti].CTipo
LEFT JOIN STipi ON STipi.C = [Documenti].Classe AND STipi.C_STipo = [Documenti].CSTipo
where [Documenti].Stato IN (4,2,3)
In particular I need to realize the SELECT IN clause, because without it my LINQ code works fine. My LINQ query is the following :
IQueryable listaDoc = null;
string _fasi = "4;2;3";
var fasi = _fasi.Split(';').Select(n => short.Parse(n)).ToList();
listaDoc = (from DOC in db.Documenti
from subdoc in db.Tipi.Where(j => j.C_Tipo == DOC.CTipo && j.C == DOC.Classe.Value).DefaultIfEmpty()
from subdoc2 in db.Stipi.Where(j => j.C_STipo == DOC.CSTIpo && j.C == DOC.Classe.Value).DefaultIfEmpty()
from subdoc3 in db.PathClassi_Web.Where(j => j.cod_class == DOC.Classe).DefaultIfEmpty()
where fasi.Contains(DOC.Stato.Value)
select new
{
DOC.ID,
DOC.Data,
DOC.Descrizione,
DOC.DAL,
DOC.AL,
DOC.Stato,
DOC.NomeDoc,
DOC.Classe,
DOC.CTipo,
DOC.CSTIpo,
DOC.SiglaRed,
DOC.Stipula,
DOC.DataCmp,
DOC.Regione,
DOC.NumDoc,
DOC.Destinazione,
DOC.DataStampa,
DOC.Ext,
GRP2 = subdoc == null ? string.Empty : subdoc.GRP2,
DESCRIZ = subdoc2 == null ? string.Empty : subdoc2.Descriz,
DESCR_CLASS = subdoc3 == null ? string.Empty : subdoc3.descr_class
});
But it returns to me 0 results. What's wrong in my LINQ query in order to reach the same result of my pure SQL query described above?
I have used the tool Linqer (http://www.sqltolinq.com/) to help me convert complex SQL-statements to linq. It saved me many times.

Entity Framework causing Timeout Error

I am working with the following Entity Framework query. I know there's a lot going on here but am hoping it's clear enough that someone might be able to spot the issue.
var lineItems = from li in Repository.Query<CostingLineItem>()
let cid = (li.ParentCostingPackage != null) ?
li.ParentCostingPackage.ParentCostingEvent.ProposalSection.Proposal.Costing.Id :
li.ParentCostingEvent.ProposalSection.Proposal.Costing.Id
where cid == costingId &&
li.OriginalProductId.HasValue &&
(li.Quantity.HasValue && li.Quantity.Value > 0) && // li.QuantityUnitMultiplier
Classifications.Contains(li.OriginalProduct.ClassificationEnumIndex)
let selectedChoiceId = li.OriginalPackageOptionId.HasValue ?
(from c in li.OriginalPackageOption.CostingLineItems
orderby (c.IsIncluded ?? false) ? -2 : (c.IsDefaultItem ?? false) ? -1 : c.Id
select (int)c.OriginalPackageOptionChoiceId).FirstOrDefault() :
0
where selectedChoiceId == 0 || (li.OriginalPackageOptionChoiceId.HasValue && li.OriginalPackageOptionId.Value == selectedChoiceId)
let hasProviderAvailable = li.OriginalProductItem.ProductItemVendors.Any(
piv => piv.ProductPricings.Any(pp => pp.ProductItemVendor.CompanyId != null || pp.ProductItemVendor.HotelId != null))
select new
{
LineItem = li,
ProductItem = li.OriginalProductItem,
Product = li.OriginalProduct,
Vendors = li.CostingLineItemVendors,
HasProviderAvailable = hasProviderAvailable
};
As is, this query generates the following run-time error:
The wait operation timed out
If I change the section that declares selectedChoiceId to the following, the error goes away:
let selectedChoiceId = 0
Can anyone see how that code is consistently causing a time-out error?
(Note: This code is part of a large application that has been running for several years. So I really don't think this has anything to do with the connection string or anything like that. If I make the change above, it works consistently.)
The query can be simplified in a number of ways, which should make it easier to optimize by the database engine.
Firstly, you can remove a number of null checks (HasValue), because they're not relevant in SQL, but they do bloat the generated SQL.
Secondly, I think this check involving selectedChoiceId can be greatly simplified. This is what I think the statement could look like:
from li in Repository.Query<CostingLineItem>()
let cid = (li.ParentCostingPackage != null) ?
li.ParentCostingPackage.ParentCostingEvent.ProposalSection.Proposal.Costing.Id :
li.ParentCostingEvent.ProposalSection.Proposal.Costing.Id
where cid == costingId &&
li.OriginalProductId.HasValue &&
li.Quantity > 0 && // no null check
Classifications.Contains(li.OriginalProduct.ClassificationEnumIndex)
let selectedChoiceId = (from c in li.OriginalPackageOption.CostingLineItems
orderby c.IsIncluded ? -2 : c.IsDefaultItem ? -1 : c.Id // no null checks
select (int)c.OriginalPackageOptionChoiceId).FirstOrDefault()
where !li.OriginalPackageOptionId.HasValue || li.OriginalPackageOptionId == selectedChoiceId
let hasProviderAvailable = li.OriginalProductItem.ProductItemVendors.Any(
piv => piv.ProductPricings.Any(pp => pp.ProductItemVendor.CompanyId != null || pp.ProductItemVendor.HotelId != null))
select new
{
LineItem = li,
ProductItem = li.OriginalProductItem,
Product = li.OriginalProduct,
Vendors = li.CostingLineItemVendors,
HasProviderAvailable = hasProviderAvailable
}
For the rest, of course there are the usual suspects. Better indexes may become more important as the database volume increases. Checking for (and fixing) database fragmentation can also have a significant impact.
I think this will give you a better performance but not sure if it'll fix the problem :
let selectedChoiceId = li.OriginalPackageOptionId.HasValue
? (from c in li.OriginalPackageOption.CostingLineItems
let cOrder = (c.IsIncluded ?? false) ? -2 : (c.IsDefaultItem ?? false) ? -1 : c.Id
orderby cOrder
select (int) c.OriginalPackageOptionChoiceId).FirstOrDefault()
: 0

How do I Take everything in a collection using Linq?

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();

Using variables in the lambda

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();

Categories