0

I have a list of a complex object with some list of objects. At the third level of the object, I have a property called ProductServiceKey. I need to get a new list of objects, in order to get those ProductServicesKeys grouped by if the dictionary called FeatureList contains the same values. Here are my object structures. I will only paste the relevant class info for this question:

Orders:

 public class Orders : IValidatableObject
{
    #region Constants
    #endregion

    #region Fields

    List<Order> _orderList;

    #endregion

    #region Events
    #endregion

    #region Properties

    /// <summary>
    /// Gets or sets the List of Order
    /// </summary>
    /// <value></value>
    public List<Order> OrderListD
    {
        get { return this._orderList; }
        set { this._orderList = value; }
    }
}

OrderListD that is of type Order:

 public class Order : IValidatableObject 
{
    #region Constants
    #endregion
    public enum OrderStatus { OrderPending, OrderSubmitted, OrderProcessed, OrderFailed, OrderNoResponse}
    public enum OrderCompletionStatus { ProductServiceUpdateFailed, ProductServiceUpdateSuccess, FeatureUpdateFailed, FeatureUpdateSuccess }

    #region Fields
    private int _orderID;
    private Guid _orderGuid;
    private System.Nullable<DateTime> _submittedOn;
    private System.Nullable<DateTime> _lastUpdatedOn;
    private List<ProductService> _services;
    private OrderStatus _status;
    private string _orderType;
    private string _errorCode = string.Empty;
    private string _errorDesc = string.Empty;

    #endregion

    #region Events
    #endregion

    #region     Properties

    public Guid OrderGuid
    {
        get
        {
            return _orderGuid;
        }
        set { this._orderGuid = value; }
    }

    public OrderStatus Status
    {
        get { return this._status; }
        set { this._status = value; }
    }

    public string Type
    {
        get { return this._orderType; }
        set { this._orderType = value; }
    }

    public string ErrorCode
    {
        get { return this._errorCode; }
        set { this._errorCode = value; }
    }

    public string ErrorDescription
    {
        get { return this._errorDesc; }
        set { this._errorDesc = value; }
    }

    /// <summary>
    /// Gets or sets the OrderID
    /// </summary>
    /// <value></value>
    public int OrderId
    {
        get { return this._orderID; }
        set { this._orderID = value; }
    }
    /// <summary>
    /// Submitted Date 
    /// </summary>
    public System.Nullable<DateTime> SubmittedOn
    {
        get { return this._submittedOn; }
        set { this._submittedOn = value; }
    }
    /// <summary>
    /// LastUpdated Date 
    /// </summary>
    public System.Nullable<DateTime> LastUpdatedOn
    {
        get { return this._lastUpdatedOn; }
        set { this._lastUpdatedOn = value; }
    }
    /// <summary>
    ///Product Services associated with the Order
    /// </summary>
    public List<ProductService> Services
    {
        get { return this._services; }
        set { this._services = value; }
    }

    public string GroupId { get; set; }

}

Services, that is a list of type ProductService:

public class ProductService : ICloneable, IValidatableObject
{

    #region Constants
    public const string PhoneType = "DPHONE";
    public const string VoicemailType = "VMAIL";
    public const string HuntGroupType = "HGROUP";
    public const string BusinessGroupType = "BGROUP";
    public const string AutoAttendantType = "AA";
    public const string AccountCodesType = "AUTH";
    #endregion

    #region Fields
    private string _autoAttendantID;
    private string _aaEditmemberID;
    private string _subscriberID;
    private string _accountDeviceID;
    private string _productServiceID;
    private string _productServiceKey;
    private string _productServiceCode;
    private string _productServiceName;
    private string _productServiceType;
    private string _productServiceStatus;
    private string _primaryProvider;
    private string _lastUpdatedOn;
    private Order.OrderCompletionStatus _productServiceOrderStatus;
    private Offer _offerRef;
    private Dictionary<string, Feature> _featureList = new Dictionary<string, Feature>(StringComparer.InvariantCultureIgnoreCase);
    private Schedule _schedule;
    private List<Profile> _profiles;
    //private Dictionary<string, Mailbox> _mailboxList;
    private List<ProductServiceAttribute<string, string>> _productServiceAttributeList;
    private string _action;
    private TWC.FeatureSet.Order.OrderStatus _status;
    private string _BPSErrorMessage = string.Empty;

    #endregion

    #region Events
    #endregion

    #region     Properties

    public Order.OrderCompletionStatus ProductServiceOrderStatus
    {
        get { return this._productServiceOrderStatus; }
        set { this._productServiceOrderStatus = value; }
    }

    public Schedule Schedule
    {
        get { return _schedule; }
        set { _schedule = value; }
    }

    public List<Profile> Profiles
    {
        get { return _profiles; }
        set { _profiles = value; }
    }

    /// <summary>
    /// Gets or sets the  MailboxList
    /// </summary>
    /// <value></value> 
    //public Dictionary<string, Mailbox> MailboxList
    //{
    //    get { return this._mailboxList; }
    //    set { this._mailboxList = value; }
    //}

    /// <summary>
    /// Gets or sets the ProductServiceID
    /// </summary>
    /// <value></value>
    public string ProductServiceId
    {
        get { return this._productServiceID; }
        set { this._productServiceID = value; }
    }

    public string ProductServiceAction
    {
        get { return this._action; }
        set { this._action = value; }
    }


    public string ProductServiceStatus
    {
        get { return this._productServiceStatus; }
        set { this._productServiceStatus = value; }
    }

    public string ProductServiceKey
    {
        get { return this._productServiceKey; }
        set { this._productServiceKey = value; }
    }

    /// <summary>
    /// Gets or sets the PoductServiceCode
    /// </summary>
    /// <value></value>
    public string ProductServiceCode
    {
        get { return this._productServiceCode; }
        set { this._productServiceCode = value; }
    }

    // <summary>
    /// Gets or sets the SubScriiberID
    /// </summary>
    /// <value></value>
    public string SubscriberId
    {
        get { return this._subscriberID; }
        set { this._subscriberID = value; }
    }
    public string AccountDeviceId
    {
        get { return this._accountDeviceID; }
        set { this._accountDeviceID = value; }
    }
    public string AutoAttendantId
    {
        get { return this._autoAttendantID; }
        set { this._autoAttendantID = value; }
    }
    public string AAEditmemberId
    {
        get { return this._aaEditmemberID; }
        set { this._aaEditmemberID = value; }
    }



    /// <summary>
    /// Gets or sets the ProductServiceName
    /// </summary>
    /// <value></value>
    public string ProductServiceName
    {
        get { return this._productServiceName; }
        set { this._productServiceName = value; }
    }

    /// <summary>
    /// Gets or sets the ProductServiceType
    /// </summary>
    /// <value></value>
    public string ProductServiceType
    {
        get { return this._productServiceType; }
        set { this._productServiceType = value; }
    }

    /// <summary>
    /// Gets or sets the PrimaryProvider
    /// </summary>
    /// <value></value>

    public string PrimaryProvider
    {
        get { return this._primaryProvider; }
        set { this._primaryProvider = value; }

    }

    /// <summary>
    /// Gets or sets the lastupdated on
    /// </summary>
    public string LastUpdatedOn
    {
        get { return this._lastUpdatedOn; }
        set { this._lastUpdatedOn = value; }

    }

    /// <summary>
    ///Offer associated with the Product service 
    /// </summary>
    public Offer OfferRef
    {
        get { return this._offerRef; }
        set { this._offerRef = value; }
    }

    /// <summary>
    ///Product Service Attribute  associated with the Product service 
    /// </summary>
    public List<ProductServiceAttribute<string, string>> ProductServiceAttributeList
    {
        get { return this._productServiceAttributeList; }
        set { this._productServiceAttributeList = value; }
    }


    /// <summary>
    ///Feature List  associated with the Product service 
    /// </summary>
    public Dictionary<string, Feature> FeatureList
    {
        get { return this._featureList; }
        set { this._featureList = value; }
    }

    public TWC.FeatureSet.Order.OrderStatus OrderStatusForService
    {
        get { return this._status; }
        set { this._status = value; }
    }
    public string BPSErrorMessage
    {
        get { return this._BPSErrorMessage; }
        set { this._BPSErrorMessage = value; }
    }

    public string Action { get; set; }
    #endregion
}

And so, when I try to group by FeatureList, I use this line of code:

var groupedOrderList = orders.OrderListD.GroupBy(u => u.Services[0].FeatureList).Select(grp => grp.First()).ToList();

My problem is that the new list called groupedOrderList created by the GroupBy, in my debugging session, has two elements instead of one. In my debuggin, FeatureList values are similar.

I also tried using the values property from the dictionary, as shown:

var groupedOrderList = orders.OrderListD.GroupBy(u => u.Services[0].FeatureList.Values).Select(grp => grp.First()).ToList();

This is driving me crazy. Why I'm not getting it grouped properly??? I should only have one element in the list, because in the 2 elements in the original list (OrderListD), it's FeatureList dictionary has the same values!!

Any help?

Thank you!

SamyCode
  • 928
  • 3
  • 14
  • 33
  • 2
    Please reduce this to a [mcve]. I very, very much doubt that you need that many properties in order to demonstrate the problem - and each of your properties that is currently represented in several lines could be a single line using automatically implemented properties. Please make it as easy as possible for us to help you. – Jon Skeet Aug 25 '20 at 17:22
  • Normally, you would hand `.GroupBy()` a field, not a list. – Robert Harvey Aug 25 '20 at 17:24
  • There is no filtering in your query so you are getting everything that is in the original list. – jdweng Aug 25 '20 at 17:26
  • 1
    The equality operator of `List` compares for reference equality which is probably not what you want. – Klaus Gütter Aug 25 '20 at 17:34
  • Jon, this should be done with auto implemented properties. You are right. I just copy/paste the code. The original code is not mine, but I will reduce the code lines to only include the properties mentioned in the problem. Robert, so there's no way to group by the values of a dictionary? There must be a way :( @jdweng thank you for your tip. What do you mean that my query doesn't has any filter? I'm grouping by FeatureList. I should get a list with everything, but just one element right? Please clarify. Thank you all. – SamyCode Aug 25 '20 at 17:34
  • @KlausGütter I thought about that. I can override the equals method but I'm not sure which field to use, following this example that uses id: https://stackoverflow.com/questions/29599910/object-equals-method-returns-false-on-seemingly-equal-object – SamyCode Aug 25 '20 at 17:36
  • `so there's no way to group by the values of a dictionary?` -- What would that look like, exactly? The purpose of `GroupBy` is to create an `IGrouping` based on one of the columns in your collection. – Robert Harvey Aug 25 '20 at 17:37
  • How exactly to you want to group? Does the equality of two `List` have to respect the order or not? – Klaus Gütter Aug 25 '20 at 17:38
  • @KlausGütter I just need the values of the properties of the dictionary value to be all equals. I don't really think orders matter. – SamyCode Aug 25 '20 at 17:42
  • @SamyCode - so you want to group by the value of the FeatureList dictionary, which in itself is a 'Feature'. What does Feature look like (apologies if it's already pasted but there was a lot of code)? – sr28 Aug 25 '20 at 17:45
  • You are grouping by u.Services[0] and if a OrderListD does not have a Services[0] the key is empty but not being removed. – jdweng Aug 25 '20 at 17:47
  • @jdweng the OrderListD will always have a Services with a first element, so Services[0] will always have a value. I'm missing something? – SamyCode Aug 25 '20 at 17:54
  • @sr28 Feature looks like this: private string _featureCode; private string _featureName; private List _attributesList; private Order.OrderCompletionStatus _featureOrderStatus; private bool _hasUpdate; and public properties for those with the same name minus the underscore. – SamyCode Aug 25 '20 at 17:55
  • @SamyCode - so you want to group by Feature? So, you're expecting all 'Feature's that are equal to be in 1 IGrouping? – sr28 Aug 25 '20 at 18:13
  • @sr28 exactly. If all the values inside feature, including the values inside AttributeList that are inside Feature also, are all the same, the group by should return a list with just one element, and that element should be a list itself of the two original elements from OrderListD list. – SamyCode Aug 25 '20 at 18:17
  • @sr28 the original list that I'm filtgering is OrderListD, which contains two elements this time. I expect these two elements to be converted to one element of IGrouping, if the Features, which are inside several levels of the OrderListD list, are equal. The final value should be a list that contains a list of the original, OrderListD list elements, but grouped by Feature. – SamyCode Aug 25 '20 at 18:19
  • 1
    @SamyCode - then I suspect you will need to provide a custom comparer to work out whether the 'Feature's are in fact equal. – sr28 Aug 25 '20 at 18:20
  • @SamyCode - here's an example of something similar: https://stackoverflow.com/questions/35128996/groupby-on-complex-object-e-g-listt?lq=1 – sr28 Aug 25 '20 at 18:21

0 Answers0