Linq update issue with lambda

I am trying to write some code in Linq with lambda. This is my first code using a lambda and I am facing a problem while updating a record. My code:

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 get an error repljoinmf_data.NotifId = "Changedxyz";

Error says: Error 2 Property or indexer "Anonymous type # 3.NotifId" cannot be assigned - it is read-only

Can someone please help me on this. I think this is because I am using var, which is anonymous, but how do I solve the problem. Any help is appreciated.

thank

+3


source to share


3 answers


As the error shows, anonymous class instances cannot be modified after they are projected.

While you can switch to a strong typed class and then reassign element properties, you still have the option to project the desired result in a previous 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, updating is not a trivial assignment, the alternatives suggested

Option # 1: strongly typed class with mutation after projection

Add new class (I 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;}
}

      

For which you can execute the project (just specify the class name instead of the anonymous one):

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

      



Then do the modification:

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

      

Option # 2 - Create a Method (or Func) that Performs Complex Logic

Since you seem to have already materialized all the data, you can use complex functions in property projections. Any accessible local variable (closure) is available to be passed in this way to the function, just like the parameters of the lambda connection(mfr, nr)

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

:

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

      

What you can use in your initial 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 
});

      

+1


source


Anonymous types immutable

and therefore created cannot be changed, you need to create a new type.
To solve your problem, you should create your own type and avoid using anonymous type when a future update is needed.
your type might look like this:

public class  ReportInfo
{
   public  int Id{get; set;} 
//the same thing  for others properties 
}

      

and your request will look like this:

new ReportInfo() { 
                Id = 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 
            })

      

than it is easy to renovate your property.



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

      

Learn more about anonymous types
and what the compiler does. When you write a line of code like this:

var o = new { property1 = expression1, ..., propertyN = expressionN };

      

the compiler describes the type of each expression, creates private fields of those assumed types, creates public readable properties for each of the fields, and creates a constructor that accepts all of these expressions. The constructor code initializes the read-only private fields from the results of the expression passed to it. In addition, the compiler overrides Equals, GetHashCode, and ToString methods and generates code inside all of these methods.

+1


source


if you want to change the "NotifId" later, you can find the entry by id and change the property.

Example:

var alias = mainframe_replication_alias.SingleOrDefault(mfr => mfr.NOTIF_ID == repljoinmf_data.NotifId);
if(alias != null)
   alias.NOTIF_ID = "Changedxyz";

      

0


source







All Articles