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 属性。

Linq Select 中的嵌套数组

由于我无法在没有 Warrant1、Warrant2 和

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(。