简体   繁体   中英

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

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();
}

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.

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; }
    }
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM