Linq使用lambda更新问题

时间:2015-05-19 12:47:09

标签: c# linq lambda

我正在尝试用Linda在Linq中编写一些代码。这是我使用lambda的第一个代码,我在更新Record时面临一个问题。 我的代码是:

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

我在repljoinmf_data.NotifId = "Changedxyz";收到错误 错误说:错误2属性或索引器'AnonymousType#3.NotifId'无法分配 - 它是只读的

有人可以帮助我。我认为这是因为我使用的是匿名的var,但是如何解决这个问题。感谢任何帮助。

由于

3 个答案:

答案 0 :(得分:1)

正如错误所示,匿名类实例一经投影就无法修改。

虽然您可以切换到强类型类,然后重新分配成员属性,但是,您有机会将前面的LINQ语句中的所需结果投影到同一个匿名类中:

pointer = malloc(sizeof(*pointer));

编辑,更新不是简单的任务,建议的替代方案

选项#1:投影后具有突变的强类型类

添加一个新类(我已经猜到了一些类型)

sizeof(*pointer)

然后您可以投影到(只需指定类名而不是匿名):

sizeof(struct Data)

然后进行修改:

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

选项#2 - 创建一个执行复杂逻辑的方法(或Func)

由于您似乎已经实现了所有数据,因此可以在属性预测中自由使用复杂函数。任何可用的局部变量(闭包)都可以传递给函数,连接lambda参数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;} }

也是如此

例如,编写一个函数来计算(mfr, nr) => new MyPoco // Not anonymous { ReportId=mfr.RPT_ID, ... 替换:

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

然后您可以在原始匿名投影中使用

(mfr, nr)

答案 1 :(得分:1)

匿名类型为immutable因此无法更改,因此您必须创建新类型 要解决您的问题,您必须创建自己的类型,并在需要进行更新时避免使用匿名类型 你的类型可能看起来像这样

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

,您的查询将如下所示

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 
            })

比您可以轻松更新您的财产

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

有关匿名类型的更多信息
编译器实际上在做什么。当你写这样一行代码时:

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

编译器推断每个表达式的类型,创建这些推断类型的私有字段,创建 每个字段的公共只读属性,并创建一个接受所有这些属性的构造函数 表达式。构造函数的代码初始化表达式结果中的私有只读字段 传递给它。此外,编译器会覆盖Object的Equals,GetHashCode和ToString 方法并在所有这些方法中生成代码。

答案 2 :(得分:0)

如果您想稍后更改'NotifId',您可以按ID找到记录并更改属性。

示例:

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