Linq without foreach? - c#

string popUpHTML="";
var xx = from Temp in TemplateList
where
(
Temp.TitleID == titleID
)
select Temp.HTML;
foreach (var s in xx)
{
popUpHTML = s.ToString();
}
The code above is working. The executed linq is supposed to return only one value. Is there any way I can get the result of the above LINQ without a foreach loop. (Sorry I am new to LINQ).
Update: titleID is a unique key in the database, hence only one result is expected.

Right now your query returns an IEnumerable, instead use FirstOrDefault() (or Single() if you are absolutely sure that there always will be exactly one result):
var popUpHTML = (from Temp in TemplateList
where Temp.TitleID == titleID
select Temp.HTML).FirstOrDefault();

var popUpHTML = TemplateList.Where(temp => temp.TitleID == titleID)
.Select(temp => temp.HTML)
.SingleOrDefault();
popUpHtml is null if there doesn't exist an item with the provided ID.

string popUpHTML =
(
from Temp in TemplateList
where ( Temp.TitleID == titleID )
select Temp.HTML
)
.FirstOrDefault();

var popUpHTML = TemplateList.FirstOrDefault(Temp => Temp.TitleID == titleID);

var xx = (from Temp in TemplateList
where
(
Temp.TitleID == titleID
)
select Temp.HTML).Take(1);

Related

Linq to XML, select query with where condition

This is my XML content:
<ListEnginsMesures>
<EnginsESC>
<NomValide>Engin_inconnu</NomValide>
<NomEquivalents>
<NomEquivalent>Engin inconnu</NomEquivalent>
<NomEquivalent>Engininconnu</NomEquivalent>
</NomEquivalents>
</EnginsESC>
<EnginsESC>
<NomValide>DRSC_6150</NomValide>
<NomEquivalents>
<NomEquivalent>DRSC 6150</NomEquivalent>
<NomEquivalent>DRSC6150</NomEquivalent>
<NomEquivalent>DRSC6.150</NomEquivalent>
<NomEquivalent>DRSC_6.150</NomEquivalent>
</NomEquivalents>
</EnginsESC>
<ListEnginsMesures>
I want to select value of 'NomValide' when i have 'NomEquivalent'.
For example :
(select 'NomValide' where 'NomEquivalent' = "Engin inconnu") will return Engin_inconnu.
(select 'NomValide' where 'NomEquivalent' = "DRSC_6.150") will return DRSC_6150.
HOW CAN I ACHIEVE THIS ONE ?
THANKS IN ADVANCE..
If you expect only one result then the following should work:
string xml=#"<ListEnginsMesures>
<EnginsESC>
<NomValide>Engin_inconnu</NomValide>
<NomEquivalents>
<NomEquivalent>Engin inconnu</NomEquivalent>
<NomEquivalent>Engininconnu</NomEquivalent>
</NomEquivalents>
</EnginsESC>
<EnginsESC>
<NomValide>DRSC_6150</NomValide>
<NomEquivalents>
<NomEquivalent>DRSC 6150</NomEquivalent>
<NomEquivalent>DRSC6150</NomEquivalent>
<NomEquivalent>DRSC6.150</NomEquivalent>
<NomEquivalent>DRSC_6.150</NomEquivalent>
</NomEquivalents>
</EnginsESC>
</ListEnginsMesures>";
var xe = XElement.Parse(xml);
var result = xe.Elements("EnginsESC")
.Where
(
x=>
x.Element("NomEquivalents")
.Elements("NomEquivalent")
.Any(n=>(string)n=="Engin inconnu")
)
.Select(x=>(string)x.Element("NomValide"))
.FirstOrDefault();
If you expect more than one results:
var results = xe.Elements("EnginsESC")
.Where
(
x=>
x.Element("NomEquivalents")
.Elements("NomEquivalent")
.Any(n=>(string)n=="Engin inconnu")
)
.Select(x=>(string)x.Element("NomValide"));

LINQ request many-to-many

I have the following tables
Users
- ID
- FirstName
- LastName
MultiplyItems
- ItemID
- Title
UserMultiplyItems
- UserID
- ItemID
I have a variable
List<int> delegateList = {1, 3, 5};
where 1, 3, 5 are ItemID
I want to select all users, where at least one ItemID linked selectable user.
I try the following:
var result = from i in _dbContext.Users
where
((delegateList == null) || i.MultiplyItems.Any(p=> delegateList.Any(a => a == p.ItemID)))
select new UserModel()
{
....
};
but it does not work. error:
Cannot compare elements of type 'System.Collections.Generic.List`1'.
Only primitive types, enumeration types and entity types are
supported.
How to do it correctly?
Thanks
I would write this one:
var filteredUsers = delegateList == null
? _dbContext.Users
: _dbContext.Users.Where(user => user.MultiplyItems
.Any(item => delegateList.Contains(item.Id)));
var result = filteredUsers.Select(user => new UserModel
{
//the UserModel initialization
});
You should not check the following line inside the query:
delegateList == null
It is translated to SQL, and SQL has no idea about what is List and how to compare it with null.
var result = from i in _dbContext.Users
from mi in i.multiplyItems
select new yourClass();
if(delegateList!=null)
{
result = result.Where(delegateList.contains(mi.ItemID));
}
result.ToList();
I dont have visual studio open to test, but it should be a lot like that.
I'm not exactly sure if this is what you wanted, but i thought its better to try and help.
This will output all users from the Users Table where the ItemID is contained in the delegateList. The magic lays in the Contains operator you can get elements from list a contained in list b
var selection = from a in db.UserMultiplyItems
from b in db.Users
where delegateList.Contains(a.ItemID) && a.UserID == b.ID
select b;
Try changing it to:
var result = from u in _dbContext.Users
where
((delegateList == null) || u.MultiplyItems.Any( mi => delegateList.Contains(mi.ItemID)))
select new UserModel()
{
....
};
Note I've also renamed your "i" and "p" things to "u" and "mi" to make it easier to read.
Alternatively you could not use LINQ at all and just stick with lambda expressions:
List<UserModel> usersWithItems =
context
.Users
.Where(u => u.MultiplyItems.Any(mi => (delegateList == null) || (delegateList.Contains(mi.ItemID))))
.Select(um => (new UserModel() { ... } ) )
.ToList();
Which personally I prefer, it means you don't need to know linq at all.

How do I return data presorted after grabbing them inside a foreach loop?

First, I'm grabbing ClientID. Then, I get all Invoices associated with that ClientID. I want to return data all ordered by InvoiceNumber, descending. Here's my code:
var rvInvoices =
(from i in db.QB_INVOICES_HEADER
where i.ClientID == cId
select i).ToList();
foreach (var itm in rvInvoices)
{
InvoiceModel cm = new InvoiceModel()
{
InvoiceNumber = itm.InvoiceNumber,
InvoiceSentDt = itm.InvoiceSentDt,
InvoiceDt = itm.InvoiceDt,
Amount = itm.Amount,
Term = itm.Term,
ClientName = itm.CI_CLIENTLIST.ClientName
};
listInvoices.Add(cm);
}
return listInvoices;
listInvoices.OrderByDescending(x => x.InvoiceNumber).ToList()
You should try something like this:
var rvInvoices =
(from i in db.QB_INVOICES_HEADER
where i.ClientID == cId
select i).OrderByDescending(x => x.InvoiceNumber);
And I don't see a reason you need to call .ToList().
You can do the order in three places.
In the initial query,
In the foreach, or
In the return
Option 1:
var rvInvoices =
(from i in db.QB_INVOICES_HEADER
where i.ClientID == cId
select i).OrderByDescending(i => i.InvoiceNumber).ToList();
Option 2:
foreach (var itm in rvInvoices.OrderByDescending(i => i.InvoiceNumber))
Option 3:
return listInvoices.OrderByDescending(i => i.InvoiceNumber).ToList();
I would suggest taking route 1 since it will run the order at the database level.
You should order them on the database instead of the client:
var rvInvoices = db.QB_INVOICES_HEADER
.Where(i => i.ClientID == cId)
.OrderByDescending(i => i.InvoiceNumber);
The method you currently have creates multiple lists, has an explicit foreach loop, and needs to have its output sorted. It can be done with just creating a single list, no explicit looping, and with the database doing the sorting for you:
return
(from i in db.QB_INVOICES_HEADER
where i.ClientID == cId
// have the database do the sorting
orderby i.InvoiceNumber descending
select i)
// break out of the DB query to make InvoiceModel
.ToEnumerable()
.Select(itm => new InvoiceModel()
{
InvoiceNumber = itm.InvoiceNumber,
InvoiceSentDt = itm.InvoiceSentDt,
InvoiceDt = itm.InvoiceDt,
Amount = itm.Amount,
Term = itm.Term,
ClientName = itm.CI_CLIENTLIST.ClientName
})
// only create one list as the last step
.ToList();

Short query for this long one

Can anybody please tell me shortest query for this :
var guestpartyids = db.CeremonyGuestParties.Where(p => p.CeremonyId == id)
.Select(p => p.GuestPartyId);
List<GuestParty> guestparties = new List<GuestParty>();
foreach (var party in guestpartyids)
{
guestparties.Add(db.GuestParties.Single(p => p.Id == party));
}
This should do it.
guestparties.AddRange(
from cgp in db.CeremonyGuestParties
where cgp.CeremonyId == id
join gp in db.GuestParties on cgp.GuestPartyId equals gp.Id
select gp
);
Please note that this will result in one database call, as where your code will result in 1+N queries. But it will not ensure there's only one matching ID, like Single() would do. This should be enforced on the database anyway, and not in code.
How about:
List<GuestParty> guestparties = from cgp in db.CeremonyGuestParties.
Where cgp.CeremonyId .id == id)
select cgp.Guestparties.ToList();

How to convert a LINQ query to use lambda expressions

I'm trying to switch this linq code to a lambda expression:
foreach (var id in orderLinesToSplit)
{
int result =
(from ol in orderLines
from splittedOl in orderLines
where ol.Key == id
&& ol.Value == splittedOl.Value
&& ol.Key != splittedOl.Key
select splittedOl.Key).FirstOrDefault();
}
The goal is to get a Dictionary<int, int> of pairs id (from oderLinesToSplit) and result (the result from the linq query). Can it be done with just one lambda expression?
Thanks
var result=
(
from ol in orderLines
from splittedOl in orderLines
where orderLinesToSplit.Contains(ol.Key)
&& ol.Value == splittedOl.Value
&& ol.Key != splittedOl.Key
select new
{
splittedOl.Key,
splittedOl.Value
}
).ToDictionary (v =>v.Key,v=>v.Value);
Or if you really want it in one expression. Then something like this:
var result=
(
db.orderLines.Join
(
db.splittedOl,
ol=>ol.Value,
splittedOl=>splittedOl.Value,
(ol,splittedOl)=>new
{
olKey=ol.Key,
splittedOlKey=splittedOl.Key
}
).Where(l =>l.olKey!= l.splittedOlKey && orderLinesToSplit.Contains(l.olKey))
.ToDictionary(l =>l.olKey,v=>v.splittedOlKey)
);
Where db is the linq data context

Categories

Resources