Find sum of unique parameter in list - linq - c#

I have list of lines, the lines contains list of calls (call has DestinationNumber property)
here's my line model
public class Line
{
public Line()
{
Calls = new List<Call>();
Messages = new List<Sms>();
Payments = new List<Payment>();
}
public int LineId { get; set; }
public int CustomerId { get; set; }
public Customer Customer { get; set; }
public Package Package { get; set; }
public ICollection<Call> Calls { get; set; }
public ICollection<Sms> Messages { get; set; }
public ICollection<Payment> Payments { get; set; }
public string LineNumber { get; set; }
public LineStatus Status { get; set; }
[DataType(DataType.DateTime)]
public DateTime? CreatedDate { get; set; }
[DataType(DataType.DateTime)]
public DateTime? RemovedDate { get; set; }
}
and here's my call model
public class Call
{
public int CallId { get; set; }
public int LineId { get; set; }
public Line Line { get; set; }
public DateTime DateOfCall { get; set; }
public int Duration { get; set; }
public string DestinationNumber { get; set; }
}
I want to Count() the number of unique calls
I tried something like that..
Lines.Sum(line=>line.Calls.Sum(call=>call.DestinationNumber.Where(/*if DestiantionNumber not counted before*/))

GroupBy approach this picks all calls by their DestinationNumber which exist only once x.Count() == 1 and counts them Count()
int result = line.Calls.GroupBy(x => x.DestinationNumber).Count(x => x.Count() == 1);

I think something like this should work:
var count = lines.SelectedMany(l => l.Calls)
.Select(c => c.DestinationNumber)
.Distinct()
.Count();

Related

Is manual foreach loop faster or linq query on collections in the following scenario?

I want to know which approach is faster. I have the following class:
public class AccountBalance
{
public long AccountID { get; set; }
public string AccountNumber { get; set; }
[NotRequiredForDataTable]
public IEnumerable<AccountMediaBalance> AccountMediaBalances { get; set; }
}
public class AccountMediaBalance
{
public long AccountID { get; set; }
public long MediaID { get; set; }
public string MediaSerialNumber { get; set; }
public decimal? CashAmount { get; set; }
public int FareID { get; set; }
public bool ShowID { get; set; }
public bool ShareCash { get; set; }
public bool ShareToken { get; set; }
public bool SharePass { get; set; }
public IEnumerable<Token> Tokens { get; set; }
public IEnumerable<Pass> Passes { get; set; }
}
public class Token
{
public long TokenID { get; set; }
public long AccountID { get; set; }
public long MediaProductID { get; set; }
public long MediaID { get; set; }
public long? ActivateByMediaID { get; set; }
public string SerialNumber { get; set; }
public decimal? TransferValue { get; set; }
public DateTimeOffset CreateTime { get; set; }
public DateTimeOffset? ActivateTime { get; set; }
public DateTimeOffset? ExpiryTime { get; set; }
}
public class Pass
{
public long MediaProductID { get; set; }
public long AccountID { get; set; }
public long MediaID { get; set; }
public int ProductID { get; set; }
public long? ActivateByMediaID { get; set; }
public string SerialNumber { get; set; }
public DateTimeOffset CreateTime { get; set; }
public DateTimeOffset? ActivateTime { get; set; }
public DateTimeOffset? ExpiryTime { get; set; }
}
I have a list of AccountBalance data as List<AccountBAlance> and I want to transform data in a way that I want to separate AccountMediaBalance collection in one list, All tokens in one list and all passes in a separate list.
There are two approaches for doing this:
public void SaveAccountBalances(List<AccountBalance> accountBalances)
{
if (accountBalances != null)
{
var mediaBalances = accountBalances.SelectMany(x => x.AccountMediaBalances ??
Enumerable.Empty<AccountMediaBalance>()).ToList();
var tokens = mediaBalances.SelectMany(x => x.Tokens ?? Enumerable.Empty<Token>()).ToList();
var passes = mediaBalances.SelectMany(x => x.Passes ?? Enumerable.Empty<Pass>()).ToList();
}
}
The other approach would be like following:
public void SaveAccountBalances(List<AccountBalance> accountBalances)
{
var mediaBalances = new List<AccountMediaBalance>();
var tokens = new List<Token>();
var passes = new List<Pass>();
if (accountBalances != null)
{
foreach (var item in accountBalances)
{
mediaBalances.AddRange(item.AccountMediaBalances ?? Enumerable.Empty<AccountMediaBalance>());
}
foreach (var item in mediaBalances)
{
tokens.AddRange(item.Tokens ?? Enumerable.Empty<Token>());
passes.AddRange(item.Passes ?? Enumerable.Empty<Pass>());
}
}
}
Performance is a big concern. Can anyone put me in the right direction and let me know which approach is faster and why?
foreach loop uses GetEnumerator directly, while linq creates the query object first and then GetEnumerator. So it is naturally a little bit faster to use foreach loop for a single iteration but it still makes the code look better to use linq.

Automapper nested mapping 3 levels

i have the following problem, i need access to items of sales line from salesheader, when i try access by entity works fine by lazy loading, but i try map with Automapper 6
canĀ“t access to Item from sales header
thanks
public class SalesHeader
{
public int DocumentNo { get; set; }
public virtual ICollection<PostedSalesLine> SalesLines { get; set; }
}
public class SalesLine
{
public int LineNo { get; set; }
public int DocumentNo { get; set; }
public int ItemId { get; set; }
public virtual Item Item { get; set; }
public int Quantity { get; set; }
public decimal Amount { get; set; }
}
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public decimal UnitCost { get; set; }
public decimal UnitPrice { get; set; }
}
var result = unitOfWork.SalesHeader.GetById(documenNo);
Mapper.Initialize(cfg => cfg.CreateMap<SalesHeader, SalesHeaderDTO>()
return Mapper.Map<SalesHeaderDTO>(result);
Done!
Dont use lazy loading, it creates a mess of proxys
public IEnumerable<SalesHeader> GetAllFullDocuments()
{
return SalesContext.SalesHeader.Include(sh => sh.SalesLines.Select(i => i.Item))
.Include(sh => sh.SellToCustomer)
.Include(sh => sh.BillToCustomer)
.ToList();
}

c# SelectMany, gather information from a nested model in a list

I am working on a project and I am trying to clean up some code. I can get the information I need using 2 lines, however I am new to using SelectMany and figure maybe I am looking at this wrong. So what I'd like to to take my two lines of code and turn it into 1 line of code if at all possible.
Selecting: I need the BambooDeployModel by a particular name, in the example 'test' is the variable for this.
Then once it narrows down my list to a particular model, I need to select the "Test" environment by name.
Here are my lines as is:
List<BambooDeployModel> deployments
var q = deployments.SelectMany(b => b.environments.Where(f => f.name == "Test"), (b, f) => f).SelectMany(f => deployments.Where(o => o.name == test)).Distinct();
var p = q.SelectMany(b => b.environments).Where(f => f.name == "Test").Distinct();
And here is the model, it is just a generic model based on values received from Bamboo based on deployments in our system.
public class BambooDeployModel
{
public int id { get; set; }
public GenericSetKey key { get; set; }
public string name { get; set; }
public GenericSetKey planKey { get; set; }
public string description { get; set; }
public List<Environment> environments { get; set; }
public Operations operations { get; set; }
}
public class GenericSetKey
{
public KeyValuePair<string, string> key { get; set; }
}
public class Environment
{
public int id { get; set; }
public GenericSetKey key { get; set; }
public string name { get; set; }
public string description { get; set; }
public int deploymentProjectId { get; set; }
public Operations operations { get; set; }
public string position { get; set; }
public string configurationState { get; set; }
}
public class Operations
{
public bool canView { get; set; }
public bool canEdit { get; set; }
public bool canDelete { get; set; }
public bool allowedToExecute { get; set; }
public bool canExecute { get; set; }
public bool allowedToCreateVersion { get; set; }
public bool allowedToSetVersionStatus { get; set; }
}

How do I make this Linq to SQL query with lambdas and includes faster?

I have this piece of code which performs quite poorly, and delays loading of web pages as a result. The objects underlying the query are not overly complicated and I only have around 6,000 rows in the time entry table, and a small number of rows in the included tables.
How can I re-write it to be more efficient? Why is it so slow? Is it the multiple includes, the lambdas, or the ToList()? When I remove the ToList() it is quite fast, but the code following this query expects a list of time entries, so I would like to find a faster alternative that still returns a list.
var timeEntries = db.TimeEntries
.Include(t => t.Assignment)
.Include(t => t.TimeStatus)
.Include(t => t.User)
.Where(t => t.UserID == strCurrentUserId)
.Where(t => t.TimeDate >= wcDate && t.TimeDate <= sundayDate)
.OrderBy(t => t.TimeDate)
.ToList();
A few of the classes are below (but, I'm not exposing my user class):
public class TimeEntry
{
[Key]
public int ID { get; set; }
public int AssignmentID { get; set; }
public virtual Assignment Assignment { get; set; }
public DateTime TimeDate { get; set; }
public decimal TimeUsed { get; set; }
public int TimeStatusID { get; set; }
public TimeStatus TimeStatus { get; set; }
public string UserID { get; set; }
public virtual User User { get; set; }
[DataType(DataType.MultilineText)]
public string Comment { get; set; }
}
public class TimeStatus
{
[Key]
public int ID { get; set; }
public string Status { get; set; }
}
public class Assignment
{
[Key]
public int ID { get; set; }
public int ProjectID { get; set; }
public virtual Project Project { get; set; }
public string UserID { get; set; }
public virtual User User { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int AssignmentStatusID { get; set; }
public AssignmentStatus AssignmentStatus { get; set; }
public decimal ChargeRate { get; set; }
public int MaxDays { get; set; }
public bool Billable { get; set; }
public bool BillableInternal { get; set; }
[Display(Name = "Assignment No.")]
public string AssignmentNumber
{
get
{
return "A" + ID.ToString("D5");
}
set { }
}
}

Get row count using group by in entityframework

I have a TheaterMovieShowTime entity in that entity I want to get the row count by grouping on a particular column say TheaterMovieDetailID .
Here is my entity :
public class TheaterMovieShowTime
{
public int TheaterMovieShowTimeID { get; set; }
public int TheaterMovieDetailID { get; set; }
public int TheaterShowTimeID { get; set; }
public virtual TheaterMovieDetail TheaterMovieDetails { get; set; }
public virtual TheaterShowTime TheaterShowTime { get; set; }
}
Here is my TheaterMovieDetail entity:
public class TheaterMovieDetail
{
public int TheaterMovieDetailID { get; set; }
public int TheaterID { get; set; }
public int MovieID { get; set; }
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public virtual Movie Movie { get; set; }
public virtual Theater Theater { get; set; }
public virtual ICollection<TheaterMovieShowTime> TheaterMovieShowTimes { get; set; }
}
I try this :
var p = _theaterMovieShowTimeService.GetAllTheaterMovieShowTime()
.GroupBy(x => x.TheaterMovieDetailID)
.Select(x => new TheaterMovieShowTimeSummaryViewModel
{
TheaterName = x.FirstOrDefault().TheaterMovieDetails.Theater.TheaterName,
MovieName = x.FirstOrDefault().TheaterMovieDetails.Movie.MovieName,
NoOfShows=???????? // get the no of rows here
});
How do I get NoOfShows here that is no of rows grouped by TheaterMovieDetailID .
Would appreciate any help offered. Let me know if you need any other information to help answer this question
Use linq Count() function:
var p = _theaterMovieShowTimeService.GetAllTheaterMovieShowTime()
.GroupBy(x => x.TheaterMovieDetailID)
.Select(x => new TheaterMovieShowTimeSummaryViewModel
{
TheaterName = x.FirstOrDefault().TheaterMovieDetails.Theater.TheaterName,
MovieName = x.FirstOrDefault().TheaterMovieDetails.Movie.MovieName,
NoOfShows= x.Count() // get the no of rows here
});

Categories