FloatLeft
FloatLeft

Reputation: 1337

Using Linq to pass data from one collection to another

I want to use LINQ to pass data from one custom collection to another. Its complicated because the collection has 2 sub collections.

Want to copy data to:

public class Quote
{
    public int Id { get; set; }
    public string Type { get; set; }
    public virtual ICollection<Rate> Rates { get; set; }
}

public class Rate
{
    public int Id { get; set; }
    public virtual ICollection<Option> Options { get; set; }
}

public class Option
{
    public int Id { get; set; }
    public decimal Price { get; set; }
}

from:

public class Quote
{
    public int QuoteId { get; set; }
    public string Type { get; set; }
    public string Destination { get; set; }
    public List<RateSet> RateSets { get; set; }
}


public class RateSet
{
    public int Id { get; set; }
    public decimal ValueMin { get; set; }
    public decimal ValueMax { get; set; }
    public List<Option> Options { get; set; }
}

public class Option
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal? Price { get; set; }
}

I was getting somewhere with this but keeping hitting problems...

newQuotes = Quotes
    .Select(x => new Quote() {
        Id = x.QuoteId,
        Rates = x.RateSets.Select( y => new Rate() {
            Id = y.Id,
            Options = y.Options.Select(z => new Option() {
                Id = z.Id,
                Price = z.Price
            }).ToList(),....

to

Upvotes: 1

Views: 3841

Answers (4)

Vlad Bezden
Vlad Bezden

Reputation: 89637

Compiled without any errors

// to
public class Quote2
{
    public int Id { get; set; }
    public string Type { get; set; }
    public virtual ICollection<Rate> Rates { get; set; }
}

public class Rate
{
    public int Id { get; set; }
    public virtual ICollection<Option2> Options { get; set; }
}

public class Option2
{
    public int Id { get; set; }
    public decimal Price { get; set; }
}

// from
public class Quote1
{
    public int QuoteId { get; set; }
    public string Type { get; set; }
    public string Destination { get; set; }
    public List<RateSet> RateSets { get; set; }
}


public class RateSet
{
    public int Id { get; set; }
    public decimal ValueMin { get; set; }
    public decimal ValueMax { get; set; }
    public List<Option1> Options { get; set; }
}

public class Option1
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal? Price { get; set; }
}

void Main()
{
    var Quotes = new List<Quote1>();

    var newQuotes = Quotes
    .Select(x => new Quote2 {
        Id = x.QuoteId,
        Rates = x.RateSets == null ? null : x.RateSets.Select( y => new Rate {
            Id = y.Id,
            Options = y.Options == null ? null : y.Options.Select(z => new Option2 {
                Id = z.Id,
                Price = z.Price.Value
            }).ToList()}).ToList()}).ToList();
}

Upvotes: 2

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174329

I would make it a bit more modular:

newQuotes = Quotes.Select(x => new Quote
                               {
                                   ID = x.QuoteID,
                                   Type = x.Type,
                                   Rates = ConvertRates(x.RateSets)
                               });

ConvertRates would use the same approach to create its sub objects and could either be a method or a Func:

ICollection<Rate> ConvertRates(IEnumerable<RateSet> oldRates)
{
    return oldRates.Select(x => new Rate
                                {
                                     ID = x.ID,
                                     Options = ConvertOptions(x.Options)
                                }).ToList();
}

Basically, this is the same approach you used, just split up and readable.

Upvotes: 1

Jay
Jay

Reputation: 6294

A simpler way may be to create methods in each class that would convert itself to the other type. Or if you don't want that kind of coupling, create a factory class that will do the conversion for you, one item at a time. Then use link to loop through and convert each item.

Like so:

public class Quote
{
    public int Id { get; set; }
    public string Type { get; set; }
    public virtual ICollection<Rate> Rates { get; set; }

    public static Quote FromData(Data.Quote input){
        if (input == null) return null;
        Quote output = new Quote()
        {
            Id = input.QuoteId,
            Type = input.Type
        };
        output.Rates = (from i in input.RateSets
                        select Rate.FromData(i)).ToList();
    }
}

public class Rate
{
    public int Id { get; set; }
    public virtual ICollection<Option> Options { get; set; }

    public static Rate FromData(Data.RateSet input)
    {
        if (input == null) return null;
        Rate output = new Rate()
        {
            Id = input.Id
        };
        output.Options = (from i in input.Options
                          select Option.FromData(i)).ToList();
        return output;
    }
}

public class Option
{
    public int Id { get; set; }
    public decimal Price { get; set; }

    public static Option FromData(Data.Option input)
    {
        if (input == null) return null;
        Option output = new Option()
        {
            Id = input.Id,
            Price = input.Price ?? 0m
        };
        return output;
    }
}

namespace Data {
    public class Quote
    {
        public int QuoteId { get; set; }
        public string Type { get; set; }
        public string Destination { get; set; }
        public List<RateSet> RateSets { get; set; }
    }


    public class RateSet
    {
        public int Id { get; set; }
        public decimal ValueMin { get; set; }
        public decimal ValueMax { get; set; }
        public List<Option> Options { get; set; }
    }

    public class Option
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal? Price { get; set; }
    }
}

Upvotes: 0

Amr
Amr

Reputation: 1995

I think what you need to do is define casting between each two corresponding classes, then cast one list into the other.

Upvotes: 0

Related Questions