我熟悉GROUP BY中的简单LINQ操作。但是我有一个复杂的场景。我需要使用分组依据将CostPageRow记录转换为CostPageSelection域对象。我们如何从列表中获取域对象?

注意:我在上面编写的分组依据没有给出List。我不确定如何写。 CostPageSelection内部有一个列表。

List<CostPageRow> costPageRows = searchDAL
    .GetAllCostPages(contextObject, searchCriteria);


var orderGroups = costPageRows
     .GroupBy(x => new {
         x.CostPage,
         x.Description,
         x.BillTypeDirect,
         x.BillTypeWarehouse,
         x.OrderType,
         x.Vendor,
         x.VendorID
     })
     .Select(y => new CostPageParent {
           CostPage = y.First().CostPage
     })
     .ToList();


存储过程的结果

public class CostPageRow
{
    //CostPage Parent

    public string CostPage { get; set; }
    public string Description { get; set; }
    public string Vendor { get; set; }
    public string VendorID { get; set; }
    public string BillTypeDirect { get; set; }
    public string BillTypeWarehouse { get; set; }
    public string OrderType { get; set; }

    //Item Chilld
    public string ItemID { get; set; }
    public string ItemDescription { get; set; }
    public string BrandCode { get; set; }
    public string PackSize { get; set; }
}


领域模型

public class CostPageSelection
{
    public CostPageParent CostPageParent { get; set; }
    public List<ItemChild> ChildItems { get; set; }
}


//CostPageParent
public class CostPageParent
{
    public int? SelectedCostPageID { get; set; }
    public string CostPage { get; set; }
    public string Description { get; set; }
    public string Vendor { get; set; }
    public string VendorID { get; set; }
    public string BillTypeDirect { get; set; }
    public string BillTypeWarehouse { get; set; }
    public string OrderType { get; set; }
}

//ItemChild
public class ItemChild
{
    public int? SelectedItemID { get; set; }
    public string ItemID { get; set; }
    public string ItemDescription { get; set; }
    public string BrandCode { get; set; }
    public string PackSize { get; set; }
}

最佳答案

从您的问题来看,您的数据库似乎包含父子关系的扁平层次结构,如果对数据库模式进行规范化以避免数据重复会更好:换句话说,每个CostPageRow行都应包含一个引用到包含相关CostPageParent实例的另一个表中(但是我想您已经有一个正在运行的数据库,这不是一个选择)。

为了解决当前的问题,您需要从每个CostPageRow实例中提取定义单个组的属性(这些属性将形成一个新的CostPageParent实例),然后使用这些CostPageParent实例创建组。唯一键,最后将组投影到CostPageSelection的新实例(每个实例都有唯一的CostPageParent键)。

创建代码后,需要修改代码以使用IGrouping<T>.Key属性获取组密钥:

var groups = costPageRows
    .GroupBy(x => new CostPageParent()
        {
            CostPage = x.CostPage,
            Description = x.Description,
            BillTypeDirect =  x.BillTypeDirect,
            BillTypeWarehouse = x.BillTypeWarehouse,
            OrderType = x.OrderType,
            Vendor = x.Vendor
        },
        new CostPageParentEqualityComparer())
    .Select(y => new CostPageSelection
        {
            CostPageParent = y.Key,
            ChildItems = y.Select(i =>
                new ItemChild()
                {
                    BrandCode = i.BrandCode,
                    ItemDescription = i.ItemDescription,
                    ItemID = i.ItemID,
                    PackSize = i.PackSize
                })
                .ToList()
        })
    .ToList();


请注意,您需要指定IEqualityComparer<CostPageParent>实现以进行分组工作属性:

class CostPageParentEqualityComparer : IEqualityComparer<CostPageParent>
{
    public bool Equals(CostPageParent x, CostPageParent y)
    {
        if (x == null)
            return y == null;

        if (object.ReferenceEquals(x, y))
            return true;

        return
            x.BillTypeDirect == y.BillTypeDirect &&
            x.BillTypeWarehouse == y.BillTypeWarehouse &&
            ...
    }

    public int GetHashCode(CostPageParent obj)
    {
        var x = 31;
        x = x * 17 + obj.BillTypeDirect.GetHashCode();
        x = x * 17 + obj.BillTypeWarehouse.GetHashCode();
        ...
        return x;
    }
}

09-06 21:22