Skip to content

Commit

Permalink
Moved Fetcher to DB from core as its fetching from DB
Browse files Browse the repository at this point in the history
  • Loading branch information
RohitM-IN committed Mar 5, 2024
1 parent fe058b0 commit 53ffcf2
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 0 deletions.
58 changes: 58 additions & 0 deletions src/Comparer/PropertyEqualityComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.Reflection;

namespace DbSyncKit.DB.Comparer
{
/// <summary>
/// Compares instances of data contracts based on specified properties, which can be either key or comparable properties.
/// </summary>
public class PropertyEqualityComparer<T> : IEqualityComparer<T>
{
/// <summary>
/// Gets the array of <see cref="PropertyInfo"/> objects representing properties used for equality comparison.
/// These properties can serve as either key or comparable properties.
/// </summary>
public readonly PropertyInfo[] properties;

/// <summary>
/// Initializes a new instance of the <see cref="PropertyEqualityComparer{T}"/> class.
/// </summary>
/// <param name="Properties">An array of <see cref="PropertyInfo"/> objects representing properties used for equality comparison. These can be either key or comparable properties.</param>
public PropertyEqualityComparer(PropertyInfo[] Properties)
{
properties = Properties;
}

/// <summary>
/// Determines whether two instances of the data contract are equal based on the specified properties.
/// </summary>
/// <param name="x">The first instance to compare.</param>
/// <param name="y">The second instance to compare.</param>
/// <returns><c>true</c> if the instances are equal; otherwise, <c>false</c>.</returns>
public bool Equals(T? x, T? y)
{
return properties.All(prop => Equals(prop.GetValue(x), prop.GetValue(y)));
}

/// <summary>
/// Returns a hash code for the specified instance of the data contract based on the specified properties.
/// </summary>
/// <param name="obj">The instance for which to get the hash code.</param>
/// <returns>A hash code for the specified instance.</returns>
public int GetHashCode(T obj)
{
unchecked
{
int hash = 17;

foreach (var prop in properties)
{
var value = prop.GetValue(obj);
hash = hash ^ ((value?.GetHashCode() ?? 0) + 23);
}

return hash;
}
}
}

}
142 changes: 142 additions & 0 deletions src/Fetcher/DataContractFetcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using DbSyncKit.DB.Comparer;
using DbSyncKit.DB.Factory;
using DbSyncKit.DB.Interface;

namespace DbSyncKit.DB.Fetcher
{
/// <summary>
/// Represents a callback function for filtering a list of data entities of type T.
/// </summary>
/// <typeparam name="T">The type of data entities to filter.</typeparam>
/// <param name="data">The list of data entities to filter.</param>
/// <returns>A filtered list of data entities.</returns>
/// <remarks>
/// This delegate defines a callback function that takes a list of data entities as input,
/// performs filtering operations on the data, and returns the filtered list.
/// </remarks>
public delegate List<T> FilterCallback<T>(List<T> data);

/// <summary>
/// Utility class for fetching data from a database using data contracts.
/// </summary>
public class DataContractFetcher
{
#region Properties

/// <summary>
/// Gets the query generator factory instance used for creating query generators.
/// </summary>
private readonly QueryGeneratorFactory Factory;

/// <summary>
/// Gets or sets the QueryGenerationManager instance for generating queries for the destination database.
/// </summary>
/// <remarks>
/// This property is set by the <see cref="RetrieveDataFromDatabases{T}(IDatabase, IDatabase, string, List{string}, PropertyEqualityComparer{T}, FilterCallback{T}?, out HashSet{T}, out HashSet{T})"/> method.
/// It allows the reuse of the QueryGenerationManager instance when the source and destination databases share the same provider.
/// </remarks>
public IQueryGenerator? DestinationQueryGenerationManager { get; private set; }

#endregion

#region Constructor

/// <summary>
/// Initializes a new instance of the <see cref="DataContractFetcher"/> class with a custom query generator factory.
/// </summary>
/// <param name="factory">The custom query generator factory instance.</param>
public DataContractFetcher(QueryGeneratorFactory factory)
{
Factory = factory;
}

#endregion

#region Methods

/// <summary>
/// Retrieves data from source and destination databases for a specified table and column list, using a specified data contract type.
/// </summary>
/// <typeparam name="T">The type of data entities to retrieve.</typeparam>
/// <param name="source">The source database.</param>
/// <param name="destination">The destination database.</param>
/// <param name="tableName">The name of the table from which to retrieve data.</param>
/// <param name="ColumnList">A list of column names to retrieve from the table.</param>
/// <param name="ComparablePropertyEqualityComparer">An equality comparer for identifying properties used in data comparison.</param>
/// <param name="filterCallback">A callback function for filtering the retrieved data.</param>
/// <param name="sourceList">An output parameter that receives the retrieved data from the source database.</param>
/// <param name="destinationList">An output parameter that receives the retrieved data from the destination database.</param>
/// <remarks>
/// The method uses a QueryGenerationManager to generate queries for retrieving data based on the specified table and columns.
/// If the providers of the source and destination databases differ, a new QueryGenerationManager is created for the destination database.
/// The retrieved data can be optionally filtered using the provided filter callback function.
/// </remarks>
public void RetrieveDataFromDatabases<T>(
IDatabase source,
IDatabase destination,
string tableName,
List<string> ColumnList,
PropertyEqualityComparer<T> ComparablePropertyEqualityComparer,
FilterCallback<T>? filterCallback,
out HashSet<T> sourceList,
out HashSet<T> destinationList)
{
var sourceQueryGenerationManager = new QueryGenerationManager(Factory.GetQueryGenerator(source.Provider));
sourceList = GetDataFromDatabase<T>(tableName, source, sourceQueryGenerationManager, ColumnList, ComparablePropertyEqualityComparer, filterCallback);

if (source.Provider != destination.Provider)
{
sourceQueryGenerationManager.Dispose();
DestinationQueryGenerationManager = new QueryGenerationManager(Factory.GetQueryGenerator(destination.Provider));
}
else
{
DestinationQueryGenerationManager = sourceQueryGenerationManager;
}

destinationList = GetDataFromDatabase<T>(tableName, destination, DestinationQueryGenerationManager, ColumnList, ComparablePropertyEqualityComparer, filterCallback);
}

/// <summary>
/// Retrieves data from a database for a specified table, columns, and data contract type.
/// </summary>
/// <typeparam name="T">The type of data entities to retrieve.</typeparam>
/// <param name="tableName">The name of the table from which to retrieve data.</param>
/// <param name="connection">The database connection.</param>
/// <param name="manager">The query generation manager for creating the SELECT query.</param>
/// <param name="columns">A list of column names to retrieve from the table.</param>
/// <param name="ComparablePropertyEqualityComparer">An equality comparer for identifying properties used in data comparison.</param>
/// <param name="filterCallback">A callback function for filtering the retrieved data.</param>
/// <returns>
/// A HashSet of data entities of type T retrieved from the specified table and columns in the database.
/// </returns>
/// <remarks>
/// The method generates a SELECT query using the provided query generation manager and executes it using a DatabaseManager.
/// The resulting data is converted to a HashSet using the specified property equality comparer for data comparison.
/// The retrieved data can be optionally filtered using the provided filter callback function.
/// </remarks>
public HashSet<T> GetDataFromDatabase<T>(
string tableName,
IDatabase connection,
IQueryGenerator manager,
List<string> columns,
PropertyEqualityComparer<T> ComparablePropertyEqualityComparer,
FilterCallback<T>? filterCallback)
{
var query = manager.GenerateSelectQuery<T>(tableName, columns, string.Empty);

using var DBManager = new DatabaseManager<IDatabase>(connection);

var data = DBManager.ExecuteQuery<T>(query, tableName);

if (filterCallback != null)
{
data = filterCallback(data);
}

return data.ToHashSet(ComparablePropertyEqualityComparer);
}

#endregion
}
}

0 comments on commit 53ffcf2

Please sign in to comment.