1

I have following class structure

public class OfferModelCollection
{
    List<OfferModel> offers = new List<OfferModel>();
}

public class OfferModel
{
     public int ID { get; set; }
     public ProviderModel Provider { get; set; }
     public ProviderType ProviderType { get; set; }   //Enum

}

public class ProviderModel : BaseModel, IIdentity
{
     public string ProviderCode { get; set; }
     public string ProviderName { get; set; }   
}

I am now trying to update ProviderType of those offers whose Provider.ProviderCode matches to some string value. How can I achieve it in LINQ?

Something like this:

offersVM.Offers.Where(x=>x.Provider.ProviderCode.Contains("p10"))).ProviderType = ProviderType.Default;
Huma Ali
  • 1,759
  • 7
  • 40
  • 66
  • What is your error? – aloisdg Nov 16 '17 at 10:31
  • 1
    The Q in Linq stands for "query", which means it's for querying, not updating things. – DavidG Nov 16 '17 at 10:31
  • You can use `.ForEach()` its not linq but its the 1 line foreach you are essentially looking for – EpicKip Nov 16 '17 at 10:33
  • This is actually an interesting question. Short answer you should not. Enumerable should be immutable the "right" way would be creating new objects in select an making a copy of the original. And since Body expressions don't work on IQueryable it's the only way. – Filip Cordas Nov 16 '17 at 10:39
  • @FilipCordas Your short answer isn't an answer. He's asking how to do it in linq not if he should. Btw take a look at the original question (the one this is a dupe of) you'd be surprised about whats possible what actually shouldn't be – EpicKip Nov 16 '17 at 10:40
  • @EpicKip That's why I added a comment not an answer. – Filip Cordas Nov 16 '17 at 10:43
  • @FilipCordas You called it an answer :) that what I was on about. Its more of a suggestion :P. I do agree though – EpicKip Nov 16 '17 at 10:44

2 Answers2

1

You have to use a foreach(at least that is the common and most efficient approach).

var toUpdate = offersVM.Offers.Where(x=> x.Provider.ProviderCode.Contains("p10"));

foreach(var x in toUpdate)
    x.ProviderType = ProviderType.Default;

Use LINQ to query a datasource, not to modify it!

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • You don't have to, look at the suggested duplicate. Also I suggest you don't answer questions when its 100% obvious the suggested dupe is actually the same – EpicKip Nov 16 '17 at 10:36
  • @EpicKip: well, you can use wrong approches if you want to force LINQ, but that's simply wrong anyway – Tim Schmelter Nov 16 '17 at 10:37
  • I'm just saying "have to" is not necessarily correct, I don't recommend using LINQ to alter. – EpicKip Nov 16 '17 at 10:38
  • 1
    Regardless if it's a good idea or not, it's still a duplicate question to a silly question... – DavidG Nov 16 '17 at 10:38
  • @DavidG Exactly my point, there is already an answer to this specific question :) – EpicKip Nov 16 '17 at 10:39
  • 1
    @EpicKip: the duplicate is actually asking for a LINQ query that modifies the source, that question is simply answered with: don't do it. This question is asking for the same but it seems OP just doesn't know that he could use a simple `foreach`. So it's possible to give him a useful answer. – Tim Schmelter Nov 16 '17 at 10:41
  • @TimSchmelter You don't answer questions with a different answer than what was asked because "it seems like the OP". If you don't know if OP knew this you could have commented instead of answered. – EpicKip Nov 16 '17 at 10:43
  • @EpicKip: why do i neeed to comment a question if i know the answer? He has a LINQ query and he wants to update a value with the filtered objects. – Tim Schmelter Nov 16 '17 at 10:44
  • @TimSchmelter Because this is not what he asked so you **don't** know the answer. Heck once you don't understand the question/start making assumptions about OP you can't answer. – EpicKip Nov 16 '17 at 10:45
  • @EpicKip: yes i did, he wants to update this property on all objects that match the given predicate. I'm pretty sure that OP doesn't want a theoretical discussion how to force this with LINQ(to save few letters) but that he has a real requirement and he needs to have a solution for this problem. Otherwise he would have shown that he could do that with a `foreach`. – Tim Schmelter Nov 16 '17 at 10:46
  • @TimSchmelter OP asked for LINQ, I think its a bit weird to assume OP doesn't know a basic foreach.... but whatever its still a dupe that you're answering, I think you know dahm well you shouldn't – EpicKip Nov 16 '17 at 10:47
  • @EpicKip: he asked for LINQ because he used a LINQ query. I think its worth mentioning that you should never modify the source in the query. Actually you should not modify anthing in a LINQ query, **don't produde side-effects**. – Tim Schmelter Nov 16 '17 at 10:48
  • @TimSchmelter Sure bud, you just keep answering duplicates alright? ;) – EpicKip Nov 16 '17 at 10:48
  • 2
    @EpicKip: i don't have the time to answer the "duplicate" although there is no good answer yet. I see this pattern far too often(`query.ToList().ForEach(...)`. I could cry everytime and it's still upvoted there. But i can answer this question to help OP. – Tim Schmelter Nov 16 '17 at 10:50
  • 1
    So why not dupe to a canonical instead? – DavidG Nov 16 '17 at 10:51
  • 1
    @DavidG: it's already closed as dup, but it would lead OP to a wrong approach, so it's helpful to provide a solution to his concrete problem **here**. – Tim Schmelter Nov 16 '17 at 10:55
  • 1
    Then add an answer on the linked dupe, not here. – DavidG Nov 16 '17 at 10:56
  • @DavidG:i have already explained why i don't do that in my last two comments – Tim Schmelter Nov 16 '17 at 10:57
0

Use foreach

foreach (var item in offersVM.Offers.Where(x=>x.Provider.ProviderCode.Contains("p10")))
{
    item.ProviderType = ProviderType.Default;
}

Linq is for accessing not mutating

staa99
  • 191
  • 1
  • 2
  • 13