diff --git a/Domca.Core/Repositories/IHydrationRepository.cs b/Domca.Core/Repositories/IHydrationRepository.cs
new file mode 100644
index 0000000..30b8508
--- /dev/null
+++ b/Domca.Core/Repositories/IHydrationRepository.cs
@@ -0,0 +1,115 @@
+using Domca.Core.Entities;
+using Domca.Core.Entities.IDs;
+
+namespace Domca.Core.Repositories;
+
+///
+/// Defines a contract for managing and retrieving hydration records within a repository.
+///
+/// This interface provides asynchronous methods for querying hydration record and synchronous methods
+/// for adding, updating, and removing hydration records. Implementations are expected to handle data persistence and ensure
+/// thread safety where appropriate. Methods that accept a allow callers to cancel
+/// ongoing operations, which is useful for long-running queries or when integrating with responsive
+/// applications.
+public interface IHydrationRepository
+{
+ // Read Methods
+ #region Read Methods
+
+ ///
+ /// Asynchronously retrieves a hydration record by its unique identifier.
+ ///
+ /// The unique identifier of the hydration record to retrieve.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation. The task result contains the hydration record if found;
+ /// otherwise, null.
+ Task GetByIdAsync(HydrationRecordId id, CancellationToken cancellationToken = default);
+
+ ///
+ /// Retrieves the hydration record associated with the specified user, if one exists.
+ ///
+ /// The identifier of the user whose hydration record is to be retrieved. Cannot be null.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation. The task result contains the hydration record for the
+ /// specified user, or null if no record is found.
+ Task?> GetByUserAsync(UserId id, CancellationToken cancellationToken = default);
+
+ ///
+ /// Retrieves all hydration records associated with the specified user.
+ ///
+ /// The unique identifier of the user whose hydration records are to be retrieved.
+ /// A cancellation token that can be used to cancel the operation.
+ /// A list of hydration records for the specified user. The list is empty if the user has no hydration records.
+ Task?> GetByUserForTodayAsync(UserId id, CancellationToken cancellationToken = default);
+
+ ///
+ /// Retrieves all hydration records for the specified user within the week containing the given reference date.
+ ///
+ /// The week is defined as starting on Monday and ending before the following Monday, based on
+ /// the provided reference date.
+ /// The unique identifier of the user whose hydration records are to be retrieved.
+ /// A date used to determine the target week. The method returns records from the week that includes this date,
+ /// starting on Monday.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A list of hydration records for the specified user that fall within the week containing the reference date. The
+ /// list is empty if no records are found.
+ Task?> GetByUserForWeekAsync(UserId id, DateTime referenceDate, CancellationToken cancellationToken = default);
+
+ ///
+ /// Retrieves all hydration records for the specified user within the given month and year.
+ ///
+ /// The unique identifier of the user whose hydration records are to be retrieved.
+ /// The month for which to retrieve records, specified as an integer from 1 (January) to 12 (December).
+ /// The year for which to retrieve records.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation. The task result contains a list of hydration records for the
+ /// specified user and month, or if no records are found.
+ Task?> GetByUserForMonthAsync(UserId id, int month, int year, CancellationToken cancellationToken = default);
+
+ ///
+ /// Retrieves all hydration records for the specified user and year asynchronously.
+ ///
+ /// The unique identifier of the user whose hydration records are to be retrieved.
+ /// The year for which to retrieve hydration records. Must be a four-digit year.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A list of hydration records for the specified user and year, or if no records are found.
+ Task?> GetByUserForYearAsync(UserId id, int year, CancellationToken cancellationToken = default);
+
+ #endregion
+
+ // Write Methods
+ #region Write Methods
+
+ ///
+ /// Adds a hydration record to the data context for tracking and persistence.
+ ///
+ /// The record is not saved to the database until changes are committed. This method does not
+ /// check for duplicate records.
+ /// The hydration record to add to the context. Cannot be null.
+ void Add(HydrationRecord hydrationRecord);
+
+ ///
+ /// Adds a collection of hydration records to the data context for insertion.
+ ///
+ /// This method stages the specified hydration records for addition to the underlying data store.
+ /// Changes are not persisted until the context is saved. If any record in the collection already exists in the
+ /// context, it may result in duplicate entries unless handled appropriately.
+ /// The collection of objects to add. Cannot be null.
+ void AddRange(List hydrationRecords);
+
+ ///
+ /// Updates the specified hydration record in the data store.
+ ///
+ /// If the specified record does not exist in the data store, no changes will be made. This
+ /// method does not save changes to the database; call SaveChanges to persist updates.
+ /// The hydration record to update. Must not be null.
+ void Update(HydrationRecord hydrationRecord);
+
+ ///
+ /// Removes the specified hydration record from the data context.
+ ///
+ /// The hydration record to remove from the context. Cannot be null.
+ void Remove(HydrationRecord hydrationRecord);
+
+ #endregion
+}
diff --git a/Domca.EntityFrameworkCore/Repositories/HydrationRepository.cs b/Domca.EntityFrameworkCore/Repositories/HydrationRepository.cs
new file mode 100644
index 0000000..e7b83dc
--- /dev/null
+++ b/Domca.EntityFrameworkCore/Repositories/HydrationRepository.cs
@@ -0,0 +1,134 @@
+using Domca.Core.Entities;
+using Domca.Core.Entities.IDs;
+using Domca.Core.Repositories;
+using Microsoft.EntityFrameworkCore;
+
+namespace Domca.EntityFrameworkCore.Repositories;
+
+///
+/// Provides access to hydration-related data operations using the specified data context.
+///
+/// The data context used to interact with the underlying hydration data store. Cannot be null.
+public class HydrationRepository(DataContext context) : IHydrationRepository
+{
+ ///
+ /// Asynchronously retrieves a hydration record by its unique identifier.
+ ///
+ /// The unique identifier of the hydration record to retrieve.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation. The task result contains the hydration record if found;
+ /// otherwise, null.
+ public async Task GetByIdAsync(HydrationRecordId id, CancellationToken cancellationToken = default)
+ => await context.HydrationRecords.FindAsync([id], cancellationToken);
+
+ ///
+ /// Asynchronously retrieves all hydration records associated with the specified user.
+ ///
+ /// The unique identifier of the user whose hydration records are to be retrieved.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation. The task result contains a list of hydration records for the specified user. The list is empty if the user has no hydration records.
+ public async Task?> GetByUserAsync(UserId id, CancellationToken cancellationToken = default)
+ => await context.HydrationRecords
+ .Where(h => h.UserId == id)
+ .ToListAsync(cancellationToken);
+
+ ///
+ /// Asynchronously retrieves all hydration records for the specified user that were created on the current UTC date.
+ ///
+ /// The method compares record dates using UTC time. If called near midnight UTC, results may
+ /// differ from local time expectations.
+ /// The unique identifier of the user whose hydration records are to be retrieved.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A list of hydration records for the specified user for today, or if no records are found.
+ public async Task?> GetByUserForTodayAsync(UserId id, CancellationToken cancellationToken = default)
+ => await context.HydrationRecords
+ .Where(h => h.UserId == id
+ && h.Date.Date == DateTime.UtcNow.Date)
+ .ToListAsync(cancellationToken);
+
+ ///
+ /// Retrieves all hydration records for the specified user within the week containing the given reference date.
+ ///
+ /// The week is defined as starting on Monday and ending before the following Monday, based on
+ /// the provided reference date.
+ /// The unique identifier of the user whose hydration records are to be retrieved.
+ /// A date used to determine the target week. The method returns records from the week that includes this date,
+ /// starting on Monday.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A list of hydration records for the specified user that fall within the week containing the reference date. The
+ /// list is empty if no records are found.
+ public async Task?> GetByUserForWeekAsync(UserId id, DateTime referenceDate, CancellationToken cancellationToken = default)
+ {
+ int diff = (7 + (referenceDate.DayOfWeek - DayOfWeek.Monday)) % 7;
+
+ var startOfWeek = referenceDate.Date.AddDays(-1 * diff);
+
+ var endOfWeek = startOfWeek.AddDays(7);
+
+ return await context.HydrationRecords
+ .Where(h => h.UserId == id
+ && h.Date >= startOfWeek
+ && h.Date < endOfWeek)
+ .ToListAsync(cancellationToken);
+ }
+
+ ///
+ /// Retrieves all hydration records for the specified user within the given month and year.
+ ///
+ /// The unique identifier of the user whose hydration records are to be retrieved.
+ /// The month for which to retrieve records, specified as an integer from 1 (January) to 12 (December).
+ /// The year for which to retrieve records.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation. The task result contains a list of hydration records for the
+ /// specified user and month, or if no records are found.
+ public async Task?> GetByUserForMonthAsync(UserId id, int month, int year, CancellationToken cancellationToken = default)
+ => await context.HydrationRecords
+ .Where(h => h.UserId == id
+ && h.Date.Month == month
+ && h.Date.Year == year)
+ .ToListAsync(cancellationToken);
+
+ ///
+ /// Retrieves all hydration records for the specified user and year.
+ ///
+ /// The unique identifier of the user whose hydration records are to be retrieved.
+ /// The year for which to retrieve hydration records. Must be a four-digit year.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A list of hydration records for the specified user and year, or if no records are found.
+ public async Task?> GetByUserForYearAsync(UserId id, int year, CancellationToken cancellationToken = default)
+ => await context.HydrationRecords
+ .Where(h => h.UserId == id
+ && h.Date.Year == year)
+ .ToListAsync(cancellationToken);
+
+ ///
+ /// Adds a hydration record to the data context for tracking and persistence.
+ ///
+ /// The record is not saved to the database until changes are committed. This method does not
+ /// check for duplicate records.
+ /// The hydration record to add to the context. Cannot be null.
+ public void Add(HydrationRecord hydrationRecord) => context.HydrationRecords.Add(hydrationRecord);
+
+ ///
+ /// Adds a collection of hydration records to the data context for insertion.
+ ///
+ /// This method stages the specified hydration records for addition to the underlying data store.
+ /// Changes are not persisted until the context is saved. If any record in the collection already exists in the
+ /// context, it may result in duplicate entries unless handled appropriately.
+ /// The collection of objects to add. Cannot be null.
+ public void AddRange(List hydrationRecords) => context.HydrationRecords.AddRange(hydrationRecords);
+
+ ///
+ /// Updates the specified hydration record in the data store.
+ ///
+ /// If the specified record does not exist in the data store, no changes will be made. This
+ /// method does not save changes to the database; call SaveChanges to persist updates.
+ /// The hydration record to update. Must not be null.
+ public void Update(HydrationRecord hydrationRecord) => context.HydrationRecords.Update(hydrationRecord);
+
+ ///
+ /// Removes the specified hydration record from the data context.
+ ///
+ /// The hydration record to remove from the context. Cannot be null.
+ public void Remove(HydrationRecord hydrationRecord) => context.HydrationRecords.Remove(hydrationRecord);
+}
\ No newline at end of file
diff --git a/Domca.EntityFrameworkCore/Repositories/UserRepository.cs b/Domca.EntityFrameworkCore/Repositories/UserRepository.cs
index b94054f..226c55d 100644
--- a/Domca.EntityFrameworkCore/Repositories/UserRepository.cs
+++ b/Domca.EntityFrameworkCore/Repositories/UserRepository.cs
@@ -24,9 +24,7 @@ public sealed class UserRepository(DataContext context) : IUserRepository
/// A task that represents the asynchronous operation. The task result contains the user entity if found; otherwise,
/// .
public async Task GetByIdAsync(UserId id, CancellationToken cancellationToken = default)
- {
- return await context.Users.FindAsync([id], cancellationToken);
- }
+ => await context.Users.FindAsync([id], cancellationToken);
///
/// Asynchronously retrieves a user whose normalized email address matches the specified value.
@@ -37,10 +35,8 @@ public sealed class UserRepository(DataContext context) : IUserRepository
/// A task that represents the asynchronous operation. The task result contains the user whose normalized email
/// address matches the specified value, or if no such user is found.
public async Task GetByEmailAsync(string email, CancellationToken cancellationToken = default)
- {
- return await context.Users
- .FirstOrDefaultAsync(u => u.EmailAddressNormalized == email.ToUpperInvariant(), cancellationToken);
- }
+ => await context.Users
+ .FirstOrDefaultAsync(u => u.EmailAddressNormalized == email.ToUpperInvariant(), cancellationToken);
///
/// Asynchronously determines whether the specified email address is not already associated with an existing user.
@@ -52,10 +48,8 @@ public sealed class UserRepository(DataContext context) : IUserRepository
/// A task that represents the asynchronous operation. The task result is if the email
/// address is unique; otherwise, .
public async Task IsEmailUniqueAsync(string email, CancellationToken cancellationToken = default)
- {
- return !await context.Users
- .AnyAsync(u => u.EmailAddressNormalized == email.ToUpperInvariant(), cancellationToken);
- }
+ => !await context.Users
+ .AnyAsync(u => u.EmailAddressNormalized == email.ToUpperInvariant(), cancellationToken);
#endregion