lambda的Linq更新问题
本文关键字:新问题 更新 Linq lambda | 更新日期: 2023-09-27 17:49:48
我正试图用lambda在Linq中编写一些代码。这是我使用lambda的第一个代码,我在更新记录时面临一个问题。我的代码是:
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属性或索引器"匿名类型#3"。NotifId'不能分配给——它是只读的
谢谢
正如错误提示的那样,匿名类实例一旦被投影就不能被修改。
虽然您可以切换到强类型类,然后重新分配成员属性,但是,您有机会将前面LINQ语句中期望的结果投影到相同的匿名类中:
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
});
编辑,更新不是琐碎的任务,建议替代
选项#1:在投影后具有突变的强类型类
添加一个新类(我已经猜到了一些类型)
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"
选项#2 -创建一个方法(或Func)来执行复杂的逻辑
既然您似乎已经物化了所有数据,那么您可以自由地在属性投影中使用复杂函数。任何可用的局部变量(闭包)都可以传递给该函数,连接lambda参数(mfr, nr)
因此,例如,写一个函数来计算您的NotifId = "Changedxyz"
替换:
private string DoIntensiveLogic(mainframe_replication mfr, NOTIF_RECIP nr)
{
// Do Stuff
}
可以在原始匿名投影中使用:
(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
});
匿名类型是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
如果您想稍后更改' notfid ',您可以通过id找到记录并更改属性。
的例子:
var alias = mainframe_replication_alias.SingleOrDefault(mfr => mfr.NOTIF_ID == repljoinmf_data.NotifId);
if(alias != null)
alias.NOTIF_ID = "Changedxyz";