LINQ grupowanie przy zależnościach 1:n

0

Zakładając, że mam strukturę jak poniżej:

    public class IdentityCard
    {
        ...
        public string OwnerId { get; set; }
        public ApplicationUser Owner { get; set; }

        public ICollection<AccountingRecord> AccountingRecords { get; set; }
    }

    public class AccountingRecord
    {
        ...

        public int IdentityCardId { get; set; }
        public IdentityCard IdentityCard { get; set; }

        [Required]
        public DateTime Timestamp { get; set; }
    }

chciałbym odfiltrować wyniki po userze, offsecie czasowym, a następnie pogrupować je po godzinie z właściwości Timestamp. Mam już coś takiego jak poniżej, ale nie potrafię poprawnie zapisać grupowania przy zależnościach 1:n.

                    var accountingIdentityCards = _context.Users
                        .Where(r => r.Id == userId)
                        .Include(s => s.IdentityCards)
                        .ThenInclude(r => r.AccountingRecords)
                        .Where(a => a.IdentityCards.Any(x => x.AccountingRecords.Any(s => s.Timestamp >= DateTime.Today.AddDays(periodOffset))) && a.IdentityCards.Any(x => x.AccountingRecords.Any(s => s.Timestamp <= DateTime.Today.AddDays(1 + periodOffset))))
                        .GroupBy(x => x.IdentityCards.AccountingRecords.Timestamp.Hour, (key, group) => new Tuple<string, int>(group.First().Timestamp.Hour.ToString(), group.Count()))
                        .ToList();

W jaki sposób poprawnie to zapisać, żeby podało liczbę rekordów w danej godzinie?

0

że takie coś?

public class IdentityCard
{
	public int Id { get; set; }
	
	public string OwnerId { get; set; }
	
	public ICollection<AccountingRecord> AccountingRecords { get; set; }
}

public class AccountingRecord
{
	public int IdentityCardId { get; set; }

	public DateTime Timestamp { get; set; }
}

public class ApplicationUser
{
	public string Id { get; set; }
	
	public string Name { get; set; }
}




var users = new List<ApplicationUser>
{
	new ApplicationUser { Id = "1", Name = "Abc" },
	new ApplicationUser { Id = "2", Name = "Asd" }
};

var dt = DateTime.Now;

var cards = new List<IdentityCard>
{
	new IdentityCard
	{
		Id = 10,
		OwnerId = "1",
		AccountingRecords = new List<AccountingRecord>
		{
			new AccountingRecord
			{
				IdentityCardId = 10,
				Timestamp = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour-2, dt.Minute, dt.Second)
			}
		}
	},
	new IdentityCard
	{
		Id = 20,
		OwnerId = "1",
		AccountingRecords = new List<AccountingRecord>
		{
			new AccountingRecord
			{
				IdentityCardId = 20,
				Timestamp = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour-1, dt.Minute, dt.Second)
			},
			new AccountingRecord
			{
				IdentityCardId = 20,
				Timestamp = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour-7, dt.Minute, dt.Second)
			},
		}
	},
	new IdentityCard
	{
		Id = 30,
		OwnerId = "1",
		AccountingRecords = new List<AccountingRecord>
		{
			new AccountingRecord
			{
				IdentityCardId = 30,
				Timestamp = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour-7, dt.Minute, dt.Second)
			},
		}
	},
	new IdentityCard
	{
		Id = 40,
		OwnerId = "2",
		AccountingRecords = new List<AccountingRecord>
		{
			new AccountingRecord
			{
				IdentityCardId = 40,
				Timestamp = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour-5, dt.Minute, dt.Second)
			},
		}
	},
	new IdentityCard
	{
		Id = 50,
		OwnerId = "2",
		AccountingRecords = new List<AccountingRecord>
		{
			new AccountingRecord
			{
				IdentityCardId = 50,
				Timestamp = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour-5, dt.Minute, dt.Second)
			},
		}
	},
};
		

var joined = from u in users join c in cards on u.Id equals c.OwnerId select new { User = u, Card = c };

var query = joined
	// ten twój predykat
	.Where(x => x.Card.AccountingRecords.Any(s => s.Timestamp > DateTime.Now.AddHours(-100)))
	.SelectMany(x => x.Card.AccountingRecords)
	.GroupBy(x => x.Timestamp)
	.Select(x => new { TimeStamp = x.Key, Cards = x.Select(a => a.IdentityCardId).ToList() })
	.ToList();

foreach (var entry in query)
{
	Console.WriteLine($"Timestamp: {entry.TimeStamp}");
	Console.WriteLine($"\t Cards: {string.Join(",", entry.Cards)}");
}
Timestamp: 06.08.2019 20:10:53
         Cards: 10
Timestamp: 06.08.2019 21:10:53
         Cards: 20
Timestamp: 06.08.2019 15:10:53
         Cards: 20,30
Timestamp: 06.08.2019 17:10:53
         Cards: 40,50
0

Ostatecznie skleciłem coś takiego i działa:

                    accountingDataDto = _context.Users
                        //    .Where(r => r.Id == userId)
                        .Include(s => s.IdentityCards)
                        .SelectMany(x => x.IdentityCards)
                        .SelectMany(x => x.AccountingRecords)
                        .Where(a => a.Timestamp >= DateTime.Today.AddDays(periodOffset) && a.Timestamp <= DateTime.Today.AddDays(1 + periodOffset))
                        .GroupBy(x => x.Timestamp.Hour)
                        .Select(x => new Tuple<int, int>(x.Key, x.Count()))
                        .ToList();

W sumie to pomogło SelectMany.

1 użytkowników online, w tym zalogowanych: 0, gości: 1