Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq update issue with lambda

Tags:

c#

lambda

linq

I am trying to write some code in Linq with lambda.This is my first code using lambda and i am facing an issue while updating Record. My code is:

using (DataClasses1DataContext db = new DataClasses1DataContext())
{

    Table<NOTIF_RECIP> NOTIF_RECIP_alias = db.GetTable<NOTIF_RECIP>();
    Table<NOTIF_SCHED> NOTIF_SCHED_alias = db.GetTable<NOTIF_SCHED>();
    Table<mainframe_replication> mainframe_replication_alias = db.GetTable<mainframe_replication>();

    var ids = NOTIF_SCHED_alias.Select(x => x.NOTIF_RPT_ID).ToArray();


    foreach (string notif_sched_data in ids)
    {
        var repljoinmf = mainframe_replication_alias
                        .Join(NOTIF_RECIP_alias,
                             mfr => mfr.RPT_ID,
                             nr => nr.NOTIF_RECIP_ID,
                             (mfr, nr) => new
                             {
                                 ReportId=mfr.RPT_ID, 
                                 Reportversion=mfr.RPT_VERS,
                                 ReportBytes= mfr.RPT_BYTES.ToString(), 
                                 ReportDate=mfr.REPL_DTM.ToString(),
                                 NotifId= mfr.NOTIF_ID,
                                 RecipAdd=nr.NOTIF_RECIP_ADDR
                             });

        foreach(var repljoinmf_data in repljoinmf)
        {
            //DO STUFF 
            repljoinmf_data.NotifId = "Changedxyz";
            //db.SubmitChanges();
        }
    }
}

I am getting Error in repljoinmf_data.NotifId = "Changedxyz"; Error says: Error 2 Property or indexer 'AnonymousType#3.NotifId' cannot be assigned to -- it is read only

Can someone please help me in this.I think it is because I am using var which is anonymous but how to solve the problem.Any help is appreciated.

Thanks

like image 888
v2v2 Avatar asked Jun 06 '26 16:06

v2v2


1 Answers

As the error suggests, anonymous class instances cannot be modified once they have been projected.

Although you could switch to a strong typed class, and then reassign the member properties, however, you have an opportunity to project the desired result in the preceding LINQ statement into the same anonymous class:

var repljoinmf = mainframe_replication_alias
.Join(NOTIF_RECIP_alias, mfr => mfr.RPT_ID, nr => nr.NOTIF_RECIP_ID, 
(mfr, nr) => new // Anon Class projection
{ 
    ReportId=mfr.RPT_ID, 
    Reportversion=mfr.RPT_VERS,
    ReportBytes= mfr.RPT_BYTES.ToString(),     
    ReportDate=mfr.REPL_DTM.ToString(),
    NotifId= "Changedxyz", // *** No need to mutate this afterwards
    RecipAdd=nr.NOTIF_RECIP_ADDR 
});

Edit, Update isn't trivial assignment, suggested alternatives

Option #1 : Strongly typed Class with mutation after projection

Add a new class (I've guessed some types)

public class MyPoco
{
     public int ReportId {get; set;}
     public string Reportversion {get; set;}
     public byte[] ReportBytes {get; set;}
     public DateTime ReportDate {get; set;}
     public int NotifId {get; set;}
     public string RecipAdd {get; set;}
}

Which you can then project into (just specify the class name instead of anonymous):

(mfr, nr) => new MyPoco // Not anonymous
{ 
    ReportId=mfr.RPT_ID, 
    ...

And then do modification afterwards:

foreach(var repljoinmf_data in repljoinmf)
{
  repljoinmf_data.NotifId = "SomeNewValue"

Option #2 - Create a method (or Func) which does the complex logic

Since you seem to have already materialized all the data, you are free to use complex functions in the property projections. Any of the available local variables (closure) are available to pass to thus function, as are the join lambda parameters (mfr, nr)

So for example, write a function to calculate your NotifId = "Changedxyz" replacement:

private string DoIntensiveLogic(mainframe_replication mfr, NOTIF_RECIP nr)
{
    // Do Stuff
}

Which you can then use in your original anonymous projection:

(mfr, nr) => new // Anon Class projection
{ 
    ReportId=mfr.RPT_ID, 
    Reportversion=mfr.RPT_VERS,
    ReportBytes= mfr.RPT_BYTES.ToString(),     
    ReportDate=mfr.REPL_DTM.ToString(),
    NotifId= DoIntensiveLogic(mfr, nr), // Call the function each row
    RecipAdd=nr.NOTIF_RECIP_ADDR 
});
like image 193
StuartLC Avatar answered Jun 08 '26 05:06

StuartLC