Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,243 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using eQuantic.Core.Data.EntityFramework.Repository;
using eQuantic.Core.Data.Repository;
using eQuantic.Core.Data.Repository.Options;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace eQuantic.Core.Data.EntityFramework.MongoDb.Repository;

public abstract class UnitOfWork : IQueryableUnitOfWork
/// <summary>
/// The MongoDB unit of work. All of the store-agnostic behaviour lives in
/// <see cref="EntityFrameworkUnitOfWork" />; this only supplies the MongoDB <see cref="Set{TEntity}" />.
/// </summary>
public abstract class UnitOfWork(IServiceProvider serviceProvider, DbContext context)
: EntityFrameworkUnitOfWork(serviceProvider, context)
{
protected readonly IServiceProvider ServiceProvider;
/// <summary>
/// The context
/// </summary>
protected readonly DbContext Context;

/// <summary>
/// The disposed
/// </summary>
protected bool Disposed;

/// <summary>
/// Initializes a new instance of the class
/// </summary>
/// <param name="serviceProvider"></param>
/// <param name="context">The context</param>
protected UnitOfWork(IServiceProvider serviceProvider, DbContext context)
{
ServiceProvider = serviceProvider;
Context = context;
}

public int Commit()
{
return Context.SaveChanges();
}

public int CommitAndRefreshChanges()
{
var changes = 0;
var saveFailed = false;

do
{
try
{
changes = Context.SaveChanges();

saveFailed = false;
}
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;

ex.Entries.ToList()
.ForEach(entry => entry.OriginalValues.SetValues(entry.GetDatabaseValues()!));
}
} while (saveFailed);

return changes;
}

public async Task<int> CommitAndRefreshChangesAsync(CancellationToken cancellationToken = default)
{
var changes = 0;
var saveFailed = false;

do
{
try
{
changes = await Context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);

saveFailed = false;
}
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;

ex.Entries.ToList()
.ForEach(entry => entry.OriginalValues.SetValues(entry.GetDatabaseValues()!));
}
} while (saveFailed);

return changes;
}

public async Task<int> CommitAsync(CancellationToken cancellationToken = default)
{
return await Context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
}

public int Commit(Action<SaveOptions> options)
{
return Commit();
}

public int CommitAndRefreshChanges(Action<SaveOptions> options)
{
return CommitAndRefreshChanges();
}

public Task<int> CommitAndRefreshChangesAsync(Action<SaveOptions> options, CancellationToken cancellationToken = default)
{
return CommitAndRefreshChangesAsync(cancellationToken);
}

public Task<int> CommitAsync(Action<SaveOptions> options, CancellationToken cancellationToken = default)
{
return CommitAsync(cancellationToken);
}

public void ApplyCurrentValues<TEntity>(TEntity original, TEntity current) where TEntity : class, IEntity
{
((Set<TEntity>)InternalCreateSet<TEntity>()).ApplyCurrentValues(original, current);
}

public void Attach<TEntity>(TEntity item) where TEntity : class, IEntity
{
((Set<TEntity>)InternalCreateSet<TEntity>()).Attach(item);
}

public void LoadCollection<TEntity, TElement>(TEntity item,
Expression<Func<TEntity, IEnumerable<TElement>>> navigationProperty,
Expression<Func<TElement, bool>>? filter = null) where TEntity : class where TElement : class
{
if (filter != null)
{
Context.Entry<TEntity>(item).Collection(navigationProperty).Query().Where(filter).Load();
}
else
{
Context.Entry<TEntity>(item).Collection(navigationProperty).Load();
}
}

public async Task LoadCollectionAsync<TEntity, TElement>(TEntity item,
Expression<Func<TEntity, IEnumerable<TElement>>> navigationProperty,
Expression<Func<TElement, bool>>? filter = null) where TEntity : class where TElement : class
{
if (filter != null)
{
await Context.Entry<TEntity>(item).Collection(navigationProperty).Query().Where(filter).LoadAsync().ConfigureAwait(false);
}
else
{
await Context.Entry<TEntity>(item).Collection(navigationProperty).LoadAsync().ConfigureAwait(false);
}
}

public void Reload<TEntity>(TEntity item) where TEntity : class
{
var entry = Context.Entry(item);
entry.CurrentValues.SetValues(entry.OriginalValues);
entry.Reload();
}

public void RollbackChanges()
{
// set all entities in change tracker
// as 'unchanged state'
Context?.ChangeTracker.Entries()
.ToList()
.ForEach(entry => entry.State = EntityState.Unchanged);
}

public void SetModified<TEntity>(TEntity item) where TEntity : class
{
//this operation also attach item in object state manager
Context.Entry<TEntity>(item).State = EntityState.Modified;
}

public virtual SaveOptions GetSaveOptions()
{
return new SaveOptions();
}

public virtual IRepository<TEntity, TKey> GetRepository<TEntity, TKey>()
where TEntity : class, IEntity<TKey>
{
return ServiceProvider.GetRequiredService<IRepository<TEntity, TKey>>();
}

public IAsyncRepository<TEntity, TKey> GetAsyncRepository<TEntity, TKey>()
where TEntity : class, IEntity<TKey>
{
return ServiceProvider.GetRequiredService<IAsyncRepository<TEntity, TKey>>();
}

public Data.Repository.ISet<TEntity> CreateSet<TEntity>() where TEntity : class, IEntity => InternalCreateSet<TEntity>();

public IQueryableRepository<TEntity, TKey> GetQueryableRepository<TEntity, TKey>()
where TEntity : class, IEntity<TKey>
{
return ServiceProvider.GetRequiredService<IQueryableRepository<TEntity, TKey>>();
}

public IAsyncQueryableRepository<TEntity, TKey> GetAsyncQueryableRepository<TEntity, TKey>()
where TEntity : class, IEntity<TKey>
{
return ServiceProvider.GetRequiredService<IAsyncQueryableRepository<TEntity, TKey>>();
}

internal DbContext GetDbContext() => Context;

internal Data.Repository.ISet<TEntity> InternalCreateSet<TEntity>() where TEntity : class, IEntity =>
protected override Data.Repository.ISet<TEntity> CreateSetCore<TEntity>() =>
new Set<TEntity>(ServiceProvider, Context);

/// <summary>
/// Disposes this instance
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Disposes the disposing
/// </summary>
/// <param name="disposing">The disposing</param>
protected virtual void Dispose(bool disposing)
{
if (Disposed)
{
return;
}

if (disposing)
{
Context?.Dispose();
}

Disposed = true;
}
}

public abstract class UnitOfWork<TDbContext>(IServiceProvider serviceProvider, TDbContext context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
<PropertyGroup>
<Description>Core Data library for Entity Framework and Mongo DB</Description>
<AssemblyTitle>eQuantic.Core.Data.EntityFramework.MongoDb</AssemblyTitle>
<Version>10.1.0.0</Version>
<Version>10.2.0.0</Version>
<TargetFramework>net10.0</TargetFramework>
<AssemblyName>eQuantic.Core.Data.EntityFramework.MongoDb</AssemblyName>
<PackageId>eQuantic.Core.Data.EntityFramework.MongoDb</PackageId>
<PackageTags>eQuantic;Core;Data;Library;Repository;Pattern;MongoDB</PackageTags>
<PackageReleaseNotes>Entity ignorant persistance with Repository Pattern for Entity
Framework</PackageReleaseNotes>

<AssemblyVersion>10.1.0.0</AssemblyVersion>
<FileVersion>10.1.0.0</FileVersion>
<AssemblyVersion>10.2.0.0</AssemblyVersion>
<FileVersion>10.2.0.0</FileVersion>

<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
<PropertyGroup>
<Description>Core Data library for Entity Framework and Mongo DB</Description>
<AssemblyTitle>eQuantic.Core.Data.EntityFramework.MongoDb</AssemblyTitle>
<Version>8.2.0.0</Version>
<Version>8.3.0.0</Version>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>eQuantic.Core.Data.EntityFramework.MongoDb</AssemblyName>
<PackageId>eQuantic.Core.Data.EntityFramework.MongoDb</PackageId>
<PackageTags>eQuantic;Core;Data;Library;Repository;Pattern;MongoDB</PackageTags>
<PackageReleaseNotes>Entity ignorant persistance with Repository Pattern for Entity
Framework</PackageReleaseNotes>

<AssemblyVersion>8.2.0.0</AssemblyVersion>
<FileVersion>8.2.0.0</FileVersion>
<AssemblyVersion>8.3.0.0</AssemblyVersion>
<FileVersion>8.3.0.0</FileVersion>

<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
Loading
Loading