LINQ- Max in where condition - c#

I have a class TaskWeekUI with this definition:
public class TaskWeekUI {
public Guid TaskWeekId { get; set; }
public Guid TaskId { get; set; }
public Guid WeekId { get; set; }
public DateTime EndDate { get; set; }
public string PersianEndDate { get; set; }
public double PlanProgress { get; set; }
public double ActualProgress { get; set; } }
and I wrote this query :
TaskWeekUI ti = tis.First( t => t.PlanProgress > 0 && t.EndDate == tis.Where(p => p.PlanProgress != null && p.PlanProgress > 0).Max(w => w.EndDate));
Is this query is true? Can I write my query better than this?

I think you want the one whose PlanProgress > 0 has a most recent EndDate.
TaskWeekUI ti = tis.Where(t => t.PlanProgress > 0)
.OrderByDescending(t => t.EndDate)
.FirstOrDefault();

This query seems to be correct from point of view of result obtained.
But in your inner query tis.Where(p => p.PlanProgress != null && p.PlanProgress > 0).Max(w => w.EndDate) is computed for each element in collection with t.PlanProgress > 0
So its a better way to obtain Max value outside of a query as follows:
var max = tis.Where(p => p.PlanProgress != null && p.PlanProgress > 0).Max(w => w.EndDate);
tis.First( t => t.PlanProgress > 0 && t.EndDate == max);
Going further p.PlanProgress != null is allways true since p.PlanProgress is not of Nullable type. So our code becomes like this:
var max = tis.Where(p => p.PlanProgress > 0).Max(w => w.EndDate);
tis.First( t => t.PlanProgress > 0 && t.EndDate == max);
Or you can change a definition of your class and make p.PlanProgress of Nullable type:
public class TaskWeekUI {
public Guid TaskWeekId { get; set; }
public Guid TaskId { get; set; }
public Guid WeekId { get; set; }
public DateTime EndDate { get; set; }
public string PersianEndDate { get; set; }
public double? PlanProgress { get; set; }
public double ActualProgress { get; set; }
}
var max = tis.Where(p => p.PlanProgress.HasValue && p.PlanProgress.Value > 0).Max(w => w.EndDate);
tis.First( t => t.PlanProgress.HasValue && t.PlanProgress.Value > 0 && t.EndDate == max);

var max_Query =
(from s in db.Songs
join bk in db.Albums on s.BookId equals addAlbumDetailsViewModel.BookId
select s.SongId).Max();
max_Query++;

You don't need compare PlanProgress with null because double is struct type, it can't be null.
If you want TaskWeekUI with Max EndDate and positive PlanProgress You can try this code:
TaskWeekUI ti = tis.Where(t => t.PlanProgress > 0).Max(w => w.EndDate);

Related

Linq group result to list of object

I'm trying group a collection of data by it's State but I'm stuck on the correct way to do this:
FileStateInfoDto
public class FileStateInfoDto : EntityDto<int>
{
public string StateName { get; set; }
public int StateNumber { get; set; }
public int FilesByStateCount { get; set; }
}
FileGroupDto
public class FileGroupDto : EntityDto<int>
{
public int CaseId { get; set; }
public string Name { get; set; }
public string ResourceKey { get; set; }
public bool IsFolder { get; set; }
public int SequenceNumber { get; set; }
public IList<FileStateInfoDto> FileStateInfo { get; set; }
public IList<FileGroupDto> FileGroups { get; set; }
public IList<FileInfoDto> Files { get; set; }
}
Here is the code I have:
return await Context.FileGroups
.Include(g => g.Case).Include(g => g.FileGroups).Include(g => g.Files)
.Where(g => g.Id == fileGroupId &&
g.CaseId == caseId &&
g.Case.CaseState != CaseState.Approved &&
g.Case.CaseState != CaseState.Submitted &&
(g.Case.CaseState != CaseState.Draft || g.Case.CreatorUserId == userId))
.OrderBy(g => g.SequenceNumber)
.Select(g => new FileGroup
{
Id = g.Id,
CaseId = g.CaseId,
Name = g.Name,
ResourceKey = g.ResourceKey,
IsFolder = g.IsFolder,
SequenceNumber = g.SequenceNumber,
FileGroups = g.FileGroups,
FileStateInfo = g.Files.GroupBy(f => f.State), <-- My problem
Files = g.Files.Where(f => f.IsActive && f.State != FileApprovalState.Approved).Select(
f => new File
{
Id = f.Id,
CreationTime = f.CreationTime,
CreatorUserId = f.CreatorUserId,
Title = f.Title,
FileName = f.FileName,
URL = f.URL,
Size = f.Size,
KeepOnPortal = f.KeepOnPortal,
CreatorUserName = Context.Users.FirstOrDefault(u => u.Id == (f.CreatorUserId ?? 0)).UserName,
CreatorUserRole = Context.CasePersons.Where(p => p.CaseId == caseId && p.UserId == f.CreatorUserId).Take(1).Select(p => p.CaseRoleType.Title).FirstOrDefault()
}
).ToList()
}).FirstOrDefaultAsync();
I'm trying to figure out how I should write this line FileStateInfo = g.Files.GroupBy(f => f.State) so it will give the expected result as below.
FileStateInfo = [{"StateName":"Approved","StateNumber":1, "FilesByStateCount":22},
{"StateName":"NotApproved","StateNumber":2, "FilesByStateCount":11}]
The State in g.Files.GroupBy(f => f.State) is an enum that contains Approved and NotApproved
StateName = Name of the State.
StateNumber = The Integer assinged.
FilesByStateCount = The files count by this state.
I hope it's possible because I've been trying to make this for a few days now.
I've tried things like this Post

Using LINQ for JOINs and Sum

I just started working with LINQ. How can I use SUM and LEFT JOIN using LINQ. I am trying to build the query below in LINQ. Is it possible?
SELECT t.TenantID, t.TenantFName, t.TenantLName, t.RentalAmount, t.PetRent, t.HousingAmount, t.UtilityCharge, t.TVCharge, t.SecurityDeposit, t.HOAFee,
t.ParkingCharge, t.StorageCharge, t.ConcessionAmount, t.ConcessionReason, t.TenantEmail, t.TenantPhone, t.CellPhoneProviderID, t.MoveInDate,
p.PropertyID, p.PropertyName,
TotalDebit, HousingDebit, TotalCredit, HousingCredit
FROM Tenants t
JOIN Properties p ON t.PropertyID = p.PropertyID
LEFT JOIN (
Select
TenantID,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID != 6 AND TenantTransactionDate <= Now() THEN TransactionAmount ELSE 0 END) AS TotalDebit,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID = 6 AND TenantTransactionDate <= Now() THEN TransactionAmount ELSE 0 END) AS HousingDebit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID != 6 AND TenantTransactionDate <= Now() THEN TransactionAmount ELSE 0 END) AS TotalCredit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID = 6 AND TenantTransactionDate <= Now() THEN TransactionAmount ELSE 0 END) AS HousingCredit
From TenantTransactions
Group By TenantID
) sums ON sums.TenantID = t.TenantID
Where t.Prospect = 2
AND t.PropertyID = 1
Thanks
Roughing out an answer and making a few assumptions about your object model, I'd start off by calculating each of the sums individually with something akin to this statement:
var tenantsTotalDebit = tenantTransactions.Where(tt.TenantId == requestedTenantId && tt.TransactionTypeID == 1 && tt.ChargeTypeID != 6 && tt.TenantTransactionDate <= DateTime.Now).Select(tt => tt.TransactionAmount).Sum();
After you've got all the sums, you can create another query that queries the Tenants and, assuming the Tenants object has it's associated Properties as a member, you could combine them in something like this:
var tenantQuery = tenants.Where(t.Prospect == 1 && t.PropertyID ==1).Select(t.TenantID, t.TenantFName, ..., tenantsTotalDebit, tenantsHousingDebit, tenantsTotalCredit, tenantsHousingCredit);
You can include values beyond the object type that you're querying in a Select() method, so you can include the precalculated sums after determining them separately.
I used classes to model you database. See code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication53
{
class Program
{
static void Main(string[] args)
{
List<Tenants> tenants = new List<Tenants>();
List<Properties> properties = new List<Properties>();
List<TenantTransactions> transactions = new List<TenantTransactions>();
var tenantTransactions = transactions.GroupBy(x => x.TenantID).Select(x => new
{
id = x.Key,
totalDebit = x.Where(y => (y.TransactionTypeID == 1) && (y.ChargeTypeID != 6) && (y.TenantTransactionDate <= DateTime.Now)).Sum(y => y.TransactionAmount),
housingDebit = x.Where(y => (y.TransactionTypeID == 1) && (y.ChargeTypeID == 6) && (y.TenantTransactionDate <= DateTime.Now)).Sum(y => y.TransactionAmount),
totalCredit = x.Where(y => (y.TransactionTypeID == 2) && (y.ChargeTypeID != 6) && (y.TenantTransactionDate <= DateTime.Now)).Sum(y => y.TransactionAmount),
housingCredit = x.Where(y => (y.TransactionTypeID == 2) && (y.ChargeTypeID == 6) && (y.TenantTransactionDate <= DateTime.Now)).Sum(y => y.TransactionAmount)
}).ToList();
var results2 = (from t in tenants
join p in properties on t.PropertyID equals p.PropertyID
join tt in tenantTransactions on t.TenantID equals tt.id into ps
from tt in ps.DefaultIfEmpty()
select new { t = t, p = p, tt = tt })
.Where(x => (x.t.PropertyID == 1) && (x.t.Prospect == 1))
.GroupBy(x => x.t.TenantID)
.Select(x => new {
tenantID = x.Key,
tenantFirstName = x.FirstOrDefault().t.TenantFName,
tenantLastName = x.FirstOrDefault().t.TenantLName,
tenantEmail = x.FirstOrDefault().t.TenantEmail,
tenantPhone = x.FirstOrDefault().t.TenantPhone,
tenantCellPhoneProvider = x.FirstOrDefault().t.CellPhoneProviderID,
properties = x.Select(y => new {
propertyID = y.p.PropertyID,
propertyName = y.p.PropertyName,
rentalAmount = y.t.RentalAmount,
petRent = y.t.PetRent,
houseingAmount = y.t.HousingAmount,
utilityCharge = y.t.UtilityCharge,
tvCharge = y.t.TVCharge,
sercurityDeposit = y.t.SecurityDeposit,
hoaFee = y.t.HousingAmount,
parkingCharge = y.t.ParkingCharge,
storageCharge = y.t.StorageCharge,
concessionAmount = y.t.ConcessionAmount,
concessionReason = y.t.ConcessionReason,
tenantMoveInDate = y.t.MoveInDate
}).ToList(),
totalDebit = x.FirstOrDefault().tt.totalDebit,
housingDebit = x.FirstOrDefault().tt.housingDebit,
totalCredit = x.FirstOrDefault().tt.totalCredit,
housingCredit = x.FirstOrDefault().tt.housingCredit,
}).ToList();
}
}
public class TenantTransactions
{
public int TenantID { get; set; }
public int TransactionTypeID{ get;set;}
public int ChargeTypeID { get;set;}
public DateTime TenantTransactionDate { get;set;}
public decimal TransactionAmount { get;set;}
}
public class Tenants
{
public int PropertyID { get; set; }
public int Prospect { get; set; }
public int TenantID { get; set; }
public string TenantFName { get; set; }
public string TenantLName { get; set; }
public decimal RentalAmount { get; set; }
public decimal PetRent { get; set; }
public decimal HousingAmount { get; set; }
public decimal UtilityCharge { get; set; }
public decimal TVCharge { get; set; }
public decimal SecurityDeposit { get; set; }
public decimal HOAFee { get; set; }
public decimal ParkingCharge { get; set; }
public decimal StorageCharge { get; set; }
public decimal ConcessionAmount { get; set; }
public string ConcessionReason { get; set; }
public string TenantEmail { get; set; }
public string TenantPhone { get; set; }
public string CellPhoneProviderID { get; set; }
public DateTime MoveInDate { get; set; }
}
public class Properties
{
public int PropertyID { get; set; }
public string PropertyName { get; set; }
}
}

Linq to entities: finding matches

I have these two EF classes:
class Row
{
public long CategoryId { get; set; }
public virtual Category Category { get; set; }
public long VesselId { get; set; }
public virtual Vessel Vessel { get; set; }
public int TruckType { get; set; }
}
class RowFilter
{
public long? CategoryId { get; set; }
public virtual Category Category { get; set; }
public long? VesselId { get; set; }
public virtual Vessel Vessel { get; set; }
public int? TruckType { get; set; }
public long? PortId { get; set; }
public virtual Port Port { get; set; }
public bool IsMatch(Row row)
{
if (CategoryId == null || CategoryId == row.CategoryId) {
if (VesselId == null || VesselId == row.VesselId) {
if (TruckType == null || TruckType == row.TruckType) {
if (PortId == null || PortId == row.Vessel.PortId) {
return true;
}
}
}
}
return false;
}
}
That is:
A Filter matches a Row if IsMatch() returns true for that row.
I have a list of rows, in an IQueryable manner:
var rows = dbContext.Rows.AsQueryable().Where(...);
...and for each row, I want to select (project) the row itself and the list of filters that match this row. I can do this easily in a Linq-to-Objects way ("in memory"):
// Linq-to-objects
rows.ToList().Select(r => new
{
row = r,
filters = dbContext.RowsFilters.Where(f => f.IsMatch(r))
};
Question is... is it possible to do it with Linq-to-Entities? (sql, not "in memory")
In a static world, I would have these navigation properties:
class Row
{
...
public virtual List<RowFilter> RowFilters { get; set; }
}
class RowFilter
{
...
public virtual List<Rows> Rows { get; set; }
}
but... that means a lot of updating: when creating a new RowFilter, when creating a new Row, etc.
You can do the following steps:
Modify the IsMatch method to return a Expression<Func<Row, bool>> type and implement it like this :
public Expression<Func<Row, bool>> IsMatch()
{
Expression<Func<Row, bool>> filter = r => (CategoryId == null || CategoryId == r.CategoryId)
&& (VesselId == null || VesselId == r.VesselId)
&& (TruckType == null || TruckType == r.TruckType)
&& (PortId == null || PortId == r.PortId);
return filter;
}
Then just use it like this :
var rowFilter = new RowFilter { PortId = 1, CategoryId = 2, TruckType = 3, VesselId = 4 };
var query = context.Rows.Where(rowFilter.IsMatch());
All the linq are translated into SQL then executed on the server side. The generated SQL by EF looks like the following:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[CategoryId] AS [CategoryId],
[Extent1].[VesselId] AS [VesselId],
[Extent1].[TruckType] AS [TruckType],
[Extent1].[PortId] AS [PortId]
FROM [dbo].[Rows] AS [Extent1]
WHERE (#p__linq__0 IS NULL OR #p__linq__1 = [Extent1].[CategoryId]) AND (#p__linq__2 IS NULL OR #p__linq__3 = [Extent1].[VesselId]) AND (#p__linq__4 IS NULL OR #p__linq__5 = [Extent1].[TruckType]) AND (#p__linq__6 IS NULL OR #p__linq__7 = CAST( [Extent1].[PortId] AS bigint))
You can use the following query:
var query = from r in context.Rows
from f in context.RowFilters.Where(f =>
(f.CategoryId == null || f.CategoryId == r.CategoryId) &&
(f.VesselId == null || f.VesselId == r.VesselId) &&
(f.TruckType == null || f.TruckType == r.TruckType) &&
(f.PortId == null || f.PortId == r.Vessel.PortId))
.DefaultIfEmpty()
let x = new {r, f}
group x by x.r
into gr
select new
{
row = gr.Key,
filters = gr.Select(y => y.f).Where(yf => yf != null)
};
var result = query.ToList();
Here is an alternative syntax:
var query = context.Rows
.SelectMany(r =>
context.RowFilters.Where(f =>
(f.CategoryId == null || f.CategoryId == r.CategoryId) &&
(f.VesselId == null || f.VesselId == r.VesselId) &&
(f.TruckType == null || f.TruckType == r.TruckType) &&
(f.PortId == null || f.PortId == r.Vessel.PortId))
.DefaultIfEmpty()
.Select(f => new {r, f}))
.GroupBy(x => x.r)
.Select(x => new
{
row = x.Key,
filters = x.Select(y => y.f).Where(yf => yf != null)
});

Tunning my dash board linq query

I have the following linq query insde my asp.net mvc web application , which mainly build our dash board, by displaying count() for many entities:-
public SystemInformation GetSystemInfo(int pagesize)
{
var d = DateTime.Today;
string[] notservers = new string[] { "vmware virtual platform", "storage device", "router", "switch", "firewall" };
string[] types = new String[] { "server", "workstation" };
var tmpCustomCount = tms.CustomAssets.Sum(a => (int?)a.Quantity);
SystemInformation s = new SystemInformation()
{
AssetCount = new AssetCount() {
CustomerCount = entities.AccountDefinitions.Count(),
RackCount = tms.TMSRacks.Count(),
ServerCount = tms.TMSServers.Count(),
VirtualMachineCount = tms.TMSVirtualMachines.Count(),
StorageDeviceCount = tms.TMSStorageDevices.Count(),
FirewallCount = tms.TMSFirewalls.Count(),
SwitchCount = tms.TMSSwitches.Count(),
RouterCount = tms.TMsRouters.Count(),
DataCenterCount = tms.DataCenters.Count(),
CustomCount = tmpCustomCount == null ? 0 : tmpCustomCount.Value
//tms.CustomAssets==null? 0 : tms.CustomAssets.Sum(a => a.Quantity)
},
AdminAudit = AllIncludingAdminAudit("", auditinfo => auditinfo.SecurityTaskType, auditinfo2 => auditinfo2.AuditAction).OrderByDescending(a => a.DateTimeStart)
.Take(pagesize).ToList(),
LatestTechnology = tms.Technologies.Where(a=> !a.IsDeleted && a.IsCompleted).OrderByDescending(a => a.TechnologyID).Take(pagesize).ToList(),
IT360ServerNo = entities.Resources
.Where(a => String.IsNullOrEmpty(a.ASSETTAG) && (a.SystemInfo.ISSERVER == true ) && !(notservers.Contains(a.SystemInfo.MODEL.Trim().ToLower()))).Count(),
IT360VMNo = entities.Resources
.Where(a => String.IsNullOrEmpty(a.ASSETTAG) && (a.SystemInfo.ISSERVER == true) && a.SystemInfo.MODEL.Trim().Equals("VMware Virtual Platform", StringComparison.OrdinalIgnoreCase)).Count(),
IT360SDNo = entities.Resources
.Where(a => String.IsNullOrEmpty(a.ASSETTAG) && a.SystemInfo.MODEL.Trim().Equals("Storage Device", StringComparison.OrdinalIgnoreCase)).Count(),
IT360SwitchNo = entities.Resources
.Where(a => String.IsNullOrEmpty(a.ASSETTAG) && a.SystemInfo.MODEL.Trim().Equals("Switch", StringComparison.OrdinalIgnoreCase)).Count(),
IT360FirewallNo = entities.Resources
.Where(a => String.IsNullOrEmpty(a.ASSETTAG) && a.SystemInfo.MODEL.Trim().Equals("Firewall", StringComparison.OrdinalIgnoreCase)).Count(),
IT360RouterNo = entities.Resources
.Where(a => String.IsNullOrEmpty(a.ASSETTAG) && a.SystemInfo.MODEL.Trim().Equals("Router", StringComparison.OrdinalIgnoreCase)).Count(),
DeleteNo = tms.TechnologyAudits.Where(a => ( EntityFunctions.TruncateTime(a.DateTimeEnd) == d && a.AuditAction.Name.ToLower() == "delete" && a.TechnologyID != null)).Count(),//TechnologyId != null so that only assets that have tags will be included in the count
CreateNo = tms.TechnologyAudits.Where(a => (EntityFunctions.TruncateTime(a.DateTimeEnd) == d && a.AuditAction.Name.ToLower() == "add" && a.TechnologyID != null)).Count(),
EditNo = tms.TechnologyAudits.Where(a => (EntityFunctions.TruncateTime(a.DateTimeEnd) == d && a.AuditAction.Name.ToLower() == "Edit" && a.TechnologyID != null)).Count(),
OtherNo = tms.TechnologyAudits.Where(a => (EntityFunctions.TruncateTime(a.DateTimeEnd) == d
&&
!((a.AuditAction.Name.ToLower() == "delete" && a.TechnologyID != null)
|| (a.AuditAction.Name.ToLower() == "add" && a.TechnologyID != null)
|| (a.AuditAction.Name.ToLower() == "edit" && a.TechnologyID != null)))).Count(),
};
return s;
}
And the model class is :-
public class SystemInformation
{
public AssetCount AssetCount { get; set; }
public IPagedList<TechnologyAudit> TechnologyAudit { get; set; }
public ICollection<AdminAudit> AdminAudit { get; set; }
public ICollection<Technology> LatestTechnology { get; set; }
[Display(Name = "Server/s")]
public int IT360ServerNo { get; set; }
[Display(Name = "VM/s")]
public int IT360VMNo { get; set; }
[Display(Name = "SD/s")]
public int IT360SDNo { get; set; }
[Display(Name = "Switch/s")]
public int IT360SwitchNo { get; set; }
[Display(Name = "Firewall/s")]
public int IT360FirewallNo { get; set; }
[Display(Name = "Router/s")]
public int IT360RouterNo { get; set; }
[Display(Name = "Delete Opeartion/s")]
public int DeleteNo { get; set; }
[Display(Name = "Create Opeartion/s")]
public int CreateNo { get; set; }
[Display(Name = "Edit Opeartion/s")]
public int EditNo { get; set; }
[Display(Name = "Other Opeartion/s")]
public int OtherNo { get; set; }
public Double HourSpan { get; set; }
public int RefreshInSeconds { get; set; }
}
The above is functioning well, but the problem is that i am sending a separate query to the DB to populate each variable such as customercount, RackCount, ServerCount ,etc...
I know that having single query to build the above might not be possible, as i am retrieving count() from separate tables. But is there a way to join the Count() on the same table to a single query, i mean to use something such as GroupBy and return the count based on the where critical ?
GroupBy could be used for calculating counts of groups with regard to specified key. In your example you use a lot of additional filtering after or before equaling to a string key. You may try with the following case, but in other cases it will be hard to apply GroupBy efficiently:
var ActionCounts = tms.TechnologyAudits.Where(a =>
(EntityFunctions.TruncateTime(a.DateTimeEnd) == d && a.TechnologyID != null))
.GroupBy(a => a.AuditAction.Name.ToLower())
.Select(g => new {
Action = g.Key
ItemCount = g.Count();
}).ToLookup(a => a.Action);
How to integrate with your code:
var tmpCustomCount = tms.CustomAssets.Sum(a => (int?)a.Quantity);
[Insert here:]
SystemInformation s = new SystemInformation()
...
DeleteNo = ActionCounts["delete"] == null ? 0 : ActionCounts["delete"].Single().ItemCount;
CreateNo = ActionCounts["add"] == null ? 0 : ActionsCount["add"].Single().ItemCount;
EditNo = ActionCounts["edit"] == null ? 0 : ActionsCount["edit"].Single().ItemCount;

Joining items in a single List<>

I have a list of custom objects called EntertainmentEvent:
public class EntertainmentEvent
{
public string Title { get; set; }
public string TagLine { get; set; }
public string Overview { get; set; }
public string ThumbnailUrl { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string EventTime { get; set; }
public Reoccurrence Reoccurrence { get; set; }
public string Url { get; set; }
}
I'd like to merge items with the same StartDate together into a single EntertainmentEvent which has a title of the two merged items concatenated together.
So far I have this:
var duplicateDates = allEvents.Join
(
allEvents, x => x.StartDate, y => y.StartDate,
(x, y) => x.Title != y.Title
? new EntertainmentEvent
{
Title = string.Format("{0}, {1}", x.Title, y.Title),
StartDate = x.StartDate
}
: null
)
.Where(x => x != null)
.ToList();
The only problem with this method is that I get duplicated items - for a sinlge date , duplicateDates list will end up with two entries
Entry 1: Startdate = 1/1/2011, Title = "Item One Title, Item Two Title"
Entry 2: Startdate = 1/1/2011, Title = "Item Two Title, Item One Title"
I'm certain there's a better way of coding this but research has come up empty thus far.
Thanks :)
var result = allEvents
.GroupBy(e => e.StartDate)
.Select(gp => new EntertainmentEvent
{
Title = string.Join(", ", gp),
StartDate = gp.Key
});
Have u tried using group by StartDate? Then u can merge all listed items into one
The following will be close, though you'll need to add Null checking and all that.
class Comparer : IEqualityComparer <EntertainmentEvent>
{
public bool Equals( EntertainmentEvent x, EntertainmentEvent y )
{
return x.Startdate == y.Startdate;
}
public int GetHashCode( EntertainmentEvent event )
{
return event.StartDate.GetHashCode();
}
}
var duplicateDates = allEvents.Join
(
allEvents, x => x.StartDate, y => y.StartDate,
(x, y) => x.Title != y.Title
? new EntertainmentEvent
{
Title = string.Format("{0}, {1}", x.Title, y.Title),
StartDate = x.StartDate
}
: null
)
.Where(x => x != null)
.Distinct( new Comparer() )
.ToList();

Categories