Using Linq to pass data from one collection to another - c#

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.

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

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

Related

How to define a multidimension array from different classes

I am trying to create object with values and a multidimensional array from a second classes. What I created:
class ProductData
{
private ProductPrices[] prices;
public string ParentName { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string TechnicalDescription { get; set; }
public bool Obsolete { get; set; }
public bool Deleted { get; set; }
public string Innercarton { get; set; }
public string Outercarton { get; set; }
public string Package { get; set; }
public string Barcode { get; set; }
public decimal Weight { get; set; }
public decimal EndUserPrice { get; set; }
public int MOQ { get; set; }
public bool ComingSoon { get; set; }
public bool NewProduct { get; set; }
public string Equivalent { get; set; }
public string ReplacedBy { get; set; }
public ProductPrices[] Prices
{
get
{
return prices;
}
set
{
prices = value;
}
}
public List<ProductFeatures> Feature { get; set; }
public List<string> Specification { get; set; }
public List<string> Image { get; set; }
public string File { get; set; }
public string Icon { get; set; }
}
class ProductFeatures
{
public string Feature;
}
public class ProductPrices
{
public decimal Price;
public int MinQuantity;
public DateTime validuntil;
public string currency;
}
Now I would like to have for the ProductPrices an multidimensional array.
So, at the end I would have something like this:
Dictionary<string, ProductData> productInfo = new Dictionary<string, ProductData>();
//Adding data to productInfo
string productName = productInfo.Name;
string description = productInfo.Description;
decimal wholesalePrice = productInfo.ProductPrices[0].Price;
int minQty = productInfo.ProductPrices[0].MinQuantity;
Somewhere I'm missing something. I've been searching around for hours trying to find it but unfortunally...
Thanks in advance!
I already found it.
Remove the private ProductPrices[] prices; and change the
public ProductPrices[] Prices
{
get
{
return prices;
}
set
{
prices = value;
}
}
to
public ProductPrices[] Prices { get; set; }
After that, you can do:
ProductData prData = new ProductData();
prData.ParentName = "Parent name";
prData.Name = "Some name";
prData.Prices = new ProductPrices[enterArrayCount];
ProductPrices prdPrices = new ProductPrices();
prdPrices.Price = Convert.ToDecimal(yourDecimalValue);
prdPrices.MinQuantity = 8;
prdPrices.Currency = "Eur";
prData.Prices[firstIndex] = prdPrices; //So firstIndex must increase after a value has been set.

Including foreign key values into a DTO for a single record

It's been a while since I have done this, but I know there is an easy way to do this that I have forgotten. Below I have a class designed to populate a single record of a data object. But I cannot get the values from another table (related by foreign key) to populate using the lambda statement because I am missing something (the two values being pulled in from another table below can be seen as dto.LeaseName and dto.CarName). How should I write the lambda for the object dm?
public StationUnloadingLogDTO GetSingleRecordforLog(int Id)
{
StationUnloadingLogDTO dto = new StationUnloadingLogDTO();
StationUnloadingLog dm = new StationUnloadingLog();
dm = entity.StationUnloadingLog
.Where(x => x.Id == Id)
.FirstOrDefault();
dto.Id = dm.Id;
dto.DateLogged = dm.DateLogged;
dto.DriverName = dm.DriverName;
dto.TruckNumber = dm.TruckNumber;
dto.CarName = dm.Carrier.CarName;
dto.CarrierId = dm.CarrierId;
dto.SpecificGravity = dm.SpecificGravity;
dto.LactMeterOpen = dm.LactMeterOpen;
dto.LactMeterClose = dm.LactMeterClose;
dto.EstimatedBarrels = dm.EstimatedBarrels;
dto.TicketNumber = dm.TicketNumber;
dto.LeaseNumber = dm.LeaseNumber;
dto.LeaseName = dm.Company.CmpName;
dto.StationId = dm.StationId;
return dto;
}
Here are the related data classes
namespace Data.Models
{
public partial class Company
{
public Company()
{
StationUnloadingLog = new HashSet<StationUnloadingLog>();
}
public string CmpId { get; set; }
public string CmpName { get; set; }
public string CmpAddress1 { get; set; }
public string CmpAddress2 { get; set; }
public int? CmpCity { get; set; }
public string CmpZip { get; set; }
public string CmpPrimaryphone { get; set; }
public ICollection<StationUnloadingLog> StationUnloadingLog { get; set; }
}
public class StationUnloadingLogDTO
{
public int Id { get; set; }
public DateTime? DateLogged { get; set; }
public string DriverName { get; set; }
public string TruckNumber { get; set; }
public string CarrierId { get; set; }
public string CarName { get; set; }
public decimal? SpecificGravity { get; set; }
public decimal? LactMeterOpen { get; set; }
public decimal? LactMeterClose { get; set; }
public int? EstimatedBarrels { get; set; }
public string TicketNumber { get; set; }
public string LeaseName { get; set; }
public string LeaseNumber { get; set; }
public string StationId { get; set; }
}
public partial class StationUnloadingLog
{
public int Id { get; set; }
public DateTime? DateLogged { get; set; }
public string DriverName { get; set; }
public string TruckNumber { get; set; }
public string CarrierId { get; set; }
public decimal? SpecificGravity { get; set; }
public decimal? LactMeterOpen { get; set; }
public decimal? LactMeterClose { get; set; }
public int? EstimatedBarrels { get; set; }
public string TicketNumber { get; set; }
public string LeaseNumber { get; set; }
public string StationId { get; set; }
public Carrier Carrier { get; set; }
public Company Company { get; set; }
public Tractorprofile Tractorprofile { get; set; }
}
public partial class Carrier
{
public Carrier()
{
StationUnloadingLog = new HashSet<StationUnloadingLog>();
}
public string CarId { get; set; }
public string CarName { get; set; }
public string CarAddress1 { get; set; }
public string CarAddress2 { get; set; }
public int? CtyCode { get; set; }
public string CarZip { get; set; }
public string CarContact { get; set; }
public ICollection<StationUnloadingLog> StationUnloadingLog { get; set; }
}
You should query for your record with child entities like this.
dm = DbSet<StationUnloadingLog>
.Where(x => x.Id == Id).Include(x => x.Carrrier)
.FirstOrDefault();

Linq To object returns 0 values

I'm trying to get some data from to Lists using Linq. If I use join with equals using one field in each list it's ok and returns number of records as expected, but if I try use join on pair of fields it returns 0 records. Why?
List<Result> inner_join =
(from egais in rests_egais
//join best in rests_best on egais.Product.AlcCode equals best.Product.AlcCode
join best in rests_best
on new {key1 = egais.Shop, key2 = egais.Product.AlcCode}
equals new { key1 = best.Shop, key2 = best.Product.AlcCode }
where egais.Quantity != best.Quantity
select new Result
{
Shop = egais.Shop,
AlcCode = egais.Product.AlcCode,
FullName = egais.Product.FullName,
Quantity_Egais = egais.Quantity,
Quantity_Best = best.Quantity,
Difference = best.Quantity - egais.Quantity
}).ToList();
EDITED: These are classes to use:
public class Rest
{
public Rest()
{
Product = new Product();
}
public string Shop { get; set; }
public DateTime Date { get; set; }
public double Quantity { get; set; }
public string InformF1RegId { get; set; }
public string InformF2RegId { get; set; }
public Product Product { get; set; }
}
public class Product
{
public Product()
{
Producer = new Producer();
}
public string FullName { get; set; }
public string AlcCode { get; set; }
public double Capacity { get; set; }
public string UnitType { get; set; }
public double AlcVolume { get; set; }
public int ProductVCode { get; set; }
public Producer Producer { get; set; }
}
public class Producer
{
public string ClientRegId { get; set; }
public string FullName { get; set; }
public string ShortName { get; set; }
public int Country { get; set; }
public string Description { get; set; }
}
public class Result
{
public string Shop { get; set; }
public string AlcCode { get; set; }
public string FullName { get; set; }
public double Quantity_Egais { get; set; }
public double Quantity_Best { get; set; }
public double Difference { get; set; }
}

IEnumerable of object returns JSON, but IEnumerable of similar object does not

I have two classes that are similar. I'm trying to see if I can simply use one. The first is in our DataModel assembly, and used in our DbContext.
public partial class type210_MotorCarrierFreightInvoice
{
public int MotorCarrierFreightInvoiceId { get; set; } // MotorCarrierFreightInvoiceId (Primary key)
public string InvoiceId { get; set; } // InvoiceId
public DateTime BillDate { get; set; } // BillDate
public string TrackingNumber { get; set; } // TrackingNumber
public decimal NetShipmentCharge { get; set; } // NetShipmentCharge
public long InterchangeTransactionDetailId { get; set; } // InterchangeTransactionDetailId
public long? BillToAddressId { get; set; } // BillToAddressId
public long? ConsigneeAddressId { get; set; } // ConsigneeAddressId
public long? ShipperAddressId { get; set; } // ShipperAddressId
// Foreign keys
public virtual interchange_TransactionDetail interchange_TransactionDetail { get; set; } // fk_Type210_MotorCarrierFreightInvoice_Interchange_TransactionDetail
public virtual typeAny_Address typeAny_Address_BillToAddressId { get; set; }
public virtual typeAny_Address typeAny_Address_ConsigneeAddressId { get; set; }
public virtual typeAny_Address typeAny_Address_ShipperAddressId { get; set; }
public type210_MotorCarrierFreightInvoice()
{
InitializePartial();
}
partial void InitializePartial();
}
The second class should represent the same object.
public class Type210MotorCarrierFreightInvoice
{
public int MotorCarrierFreightInvoiceId { get; set; }
public string InvoiceId { get; set; }
public DateTime BillDate { get; set; }
public string TrackingNumber { get; set; }
public decimal NetShipmentCharge { get; set; }
public long InterchangeTransactionDetailId { get; set; }
public Address BillToAddress { get; set; }
public Address ConsigneeAddress { get; set; }
public Address ShipperAddress { get; set; }
}
I'm working with a WebApi service that will expose the data via JSON. Basically what I'm trying is this:
[Route("api/Subscriber/Get210sNew/{transactionId}")]
[Route("api/Subscriber/Get210sNew/{transactionId}/{limit}")]
public IEnumerable<type210_MotorCarrierFreightInvoice> Get210sDOES_NOT_WORK(int transactionId, int limit = DefaultLimit)
{
var key = new QueryAfterId(transactionId, limit);
var dataService = new Type210DataService(_ediContext);
return dataService
.Get(key)
.Select(x => x);
}
[Route("api/Subscriber/Get210s/{transactionId}")]
[Route("api/Subscriber/Get210s/{transactionId}/{limit}")]
public IEnumerable<type210_MotorCarrierFreightInvoice> Get210sWorks(int transactionId, int limit = DefaultLimit)
{
var key = new QueryAfterId(transactionId, limit);
var dataService = new Type210DataService(_ediContext);
return dataService
.Get(key)
.Select(Map);
}
Here is the Map method:
private static Type210MotorCarrierFreightInvoice Map(
type210_MotorCarrierFreightInvoice dbNotice)
{
return new Type210MotorCarrierFreightInvoice
{
MotorCarrierFreightInvoiceId = dbNotice.MotorCarrierFreightInvoiceId,
InvoiceId = dbNotice.InvoiceId,
BillDate = dbNotice.BillDate,
ShipDate = dbNotice.ShipDate,
TrackingNumber = dbNotice.TrackingNumber,
PurchaseOrderNumber = dbNotice.PurchaseOrderNumber,
BillOfLading = dbNotice.BillOfLading,
NetShipmentCharge = dbNotice.NetShipmentCharge,
InterchangeTransactionDetailId = dbNotice.InterchangeTransactionDetailId,
BillToAddress = Mapper.MapToAddress(dbNotice.typeAny_Address_BillToAddressId),
ConsigneeAddress = Mapper.MapToAddress(dbNotice.typeAny_Address_ConsigneeAddressId),
ShipperAddress = Mapper.MapToAddress(dbNotice.typeAny_Address_ShipperAddressId)
};
}
Get210sWorks will return Json data to the browser. Get210sDOES_NOT_WORK does not. Both queries get the same number of records. But Get210sDOES_NOT_WORK shows no records in the browser window.
Why can't I return an IEnumerable of my DataModel class as Json?

Getting the Object From IGrouping in c#

I need to Access available Hotel Object From query2, here I am able to access HotelCode value using y.key, but How Can I Access the availableHotel Object from query2.
My Matrix MOdel
public class JsonMatrixModel
{
public class Result
{
public string responseId { get; set; }
public string searchId { get; set; }
public int totalFound { get; set; }
public List<availableHotels> availableHotels { get; set; }
}
public class availableHotels
{
public string processId { get; set; }
public string hotelCode { get; set; }
public string availabilityStatus { get; set; }
public double totalPrice { get; set; }
public double totalTax { get; set; }
public double totalSalePrice { get; set; }
public string currency { get; set; }
public string boardType { get; set; }
public List<rooms> rooms { get; set; }
}
public class rooms
{
public string roomCategory { get; set; }
public List<paxes> paxes { get; set; }
public double totalRoomRate { get; set; }
public List<ratesPerNight> ratesPerNight { get; set; }
}
public class paxes
{
public string paxType { get; set; }
public int age { get; set; }
}
public class ratesPerNight
{
public string date { get; set; }
public double amount { get; set; }
}
}
My Query
Enumerable<IGrouping<string, JsonMatrixModel.availableHotels>> quer2 =
from ff in ddd
from ss in ff.availableHotels.OrderBy(x =>x.totalSalePrice) group ss by ss.hotelCode;
Accessing the Value
foreach (var y in quer2)
{
string ss = y.Key;
}
After you make the grouping, make a projection to a new anonymous object with a property that will have the value of your key, and another could the the list of grouped values for that key.
var quer2 =
from ff in ddd
from ss in ff.availableHotels.OrderBy(x =>x.totalSalePrice)
group ss by ss.hotelCode
select new
{
GroupKey = ss.Key,
GroupValuesList = ss.ToList()
};
Console.WriteLine(quer2.First().GroupKey);
IGroupping is just an IEnumerable with an additional Key property. is this what you want?
var groups = items.GroupBy(p => p.Property);
foreach (var group in groups)
{
Console.WriteLine(group.Key);
foreach (var item in group)
{
Console.WriteLine("\t{0}", item.AnotherProperty);
}
}

Categories