Linq Select 中的嵌套数组
本文关键字:嵌套 数组 Select Linq | 更新日期: 2023-09-27 18:34:34
我正在尝试使用包含嵌套类数组的 LINQ 填充实例。我已经设法使用以下 LINQ 执行此操作。我还在选择中包含了构成实例的类。
select new EditableWarrantBook {
Id = p1.id,
Comment = p1.EntryComment,
WarrantYear1 = new BookYear {
StatusYear = p2.StatusYear,
Status = p2.Status,
},
WarrantYear2 = new BookYear {
StatusYear = p3.StatusYear,
Status = p3.Status,
},
WarrantYear3 = new BookYear {
StatusYear = p4.StatusYear,
Status = p4.Status,
}
}
public class EditableWarrantBook
{
public int Id { get; set; }
public string Comment { get; set; }
public BookYear[] WarrantYear = new BookYear[3];
public BookYear WarrantYear1
{
get { return WarrantYear[0]; }
set { WarrantYear[0] = value; }
}
public BookYear WarrantYear2
{
get { return WarrantYear[1]; }
set { WarrantYear[1] = value; }
}
public BookYear WarrantYear3
{
get { return WarrantYear[2]; }
set { WarrantYear[2] = value; }
}
}
public class BookYear
{
public int? StatusYear { get; set; }
public string Status { get; set; }
}
这行得通,我可以使用WarrantYear[0]
或WarrantYear1
访问值。这在设计 UI 时有时很有用。但是,在这种情况下,我不需要 WarrantYear1
属性,因为我要将其转换为 JSON,并且不需要重复(或想在网络上发送相同数据的两个版本(。我的问题是,如何编写选择语句来加载 WarrantYear 数组。或者如何编写类,以便我可以将数组作为属性进行访问。我的解决方案不应包含 EditableWarrantBook
类中的 Warrant1, Warrant2, Warrant3
属性。
Warrant3 属性的情况下让选择工作,我保持原样并重写了该类,以便 JSON 序列化程序将创建一个没有 Warrant1、Warrant2 和 Warrant3 属性的 JSON 实例。我使用了这篇文章中的反思。为了澄清这个问题,我的第一次尝试是创建一个 JSON 有效负载,该有效负载是其必须的两倍,因为 JSON 序列化程序同时创建了 Warrant1、Warrant2 和 Warrant3 结构以及 Warrant[] 数组。仅使用 Warrant[] 数组为JSON 结果重写基类满足了我的 Web 服务的接口要求。
namespace my.Models
{
public class WarrantBook
{
public int Id { get; set; }
public string Comment { get; set; }
BookYear[] warrantYear = new BookYear[3];
public BookYear[] WarrantYear
{
get { return warrantYear; }
set { warrantYear = value; }
}
}
public class EditableWarrantBook : WarrantBook
{
public BookYear WarrantYear1
{
get { return WarrantYear[0]; }
set { WarrantYear[0] = value; }
}
public BookYear WarrantYear2
{
get { return WarrantYear[1]; }
set { WarrantYear[1] = value; }
}
public BookYear WarrantYear3
{
get { return WarrantYear[2]; }
set { WarrantYear[2] = value; }
}
}
public class BookYear
{
public int? StatusYear { get; set; }
public string Status { get; set; }
}
public static class Ext
{
public static void CopyProperties(this EditableWarrantBook source, WarrantBook destination)
{
// Iterate the Properties of the destination instance and
// populate them from their source counterparts
PropertyInfo[] destinationProperties = destination.GetType().GetProperties();
foreach (PropertyInfo destinationPi in destinationProperties)
{
PropertyInfo sourcePi = source.GetType().GetProperty(destinationPi.Name);
destinationPi.SetValue(destination, sourcePi.GetValue(source, null), null);
}
}
}
}
用法 WCF REST Web 服务
[WebGet(UriTemplate = "GetWarrant?id={s}&user={user}")]
public WarrantBook GetWarrant(string s, string user)
{
int id;
if (int.TryParse(s, out id))
{
EditableWarrantBook model = SessionWarrantBook.One(p => p.Id == id);
model.CheckedOutBy = user; // need to add checkout code
WarrantBook jsonModel = new WarrantBook();
model.CopyProperties(jsonModel);
return jsonModel;
}
return new WarrantBook();
}
问题是您正在尝试将SQL世界(构建查询(与CLR世界(创建新对象(混合在一起。解决此问题的方法是将查询分解为初始数据获取查询(SQL 世界(,然后枚举结果以转换为对象(CLR 世界(:
所以在where p1.SaleYear == 2009
之后,添加这个:
select new { p1, p2, p3, p4 })
.AsEnumerable()
.Select(tr => new EditableWarrantBook
{
Id = tr.p1.id,
Comment = tr.p1.EntryComment,
WarrantYear = new[] {
tr.p2 == null ? (BookYear)null : new BookYear // EDITED LINE
{
StatusYear = tr.p2.StatusYear,
Status = tr.p2.Status,
},
tr.p3 == null ? (BookYear)null : new BookYear // EDITED LINE
{
StatusYear = tr.p3.StatusYear,
Status = tr.p3.Status,
},
tr.p4 == null ? (BookYear)null : new BookYear // EDITED LINE
{
StatusYear = tr.p4.StatusYear,
Status = tr.p4.Status,
}}
}).ToList();
如果要保留查询语法,只需将其更改为:
result = from tr in
(/*Select up to the AsEnumerable call above)*/).AsEnumerable()
select new EditableWarrantBook
{
/* Initialization code supplied above */
}
编辑:所以我再次修改了示例。看起来您返回的值之一是 null,因此我添加了一个 null 检查以确保您没有访问 null 对象的属性(尽管我没有检查 null p1
(。