using System.Diagnostics; using Gremlin_BlazorServer.Data.DBClasses; using Gremlin_BlazorServer.Data.EntityClasses; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Metadata; namespace Gremlin_BlazorServer.Services; public class GenericController { private static readonly GremlinDb gremlinDb = new(); public static IList? GetAll(string include) where TResult : class, IMetadata { try { return gremlinDb.Set().Include(include).ToList(); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return null; } } public static IList? GetAll(Predicate search) where TResult : class, IMetadata { ArgumentNullException.ThrowIfNull(search); try { return gremlinDb.Set().AsEnumerable().Where(t => search(t)).ToList(); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return null; } } public static async Task?> GetAllAsync() where TResult : class, IMetadata { try { return await gremlinDb.Set().ToListAsync(); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return null; } } public async Task?> GetAllAsync(string include) where TResult : class, IMetadata { try { return await gremlinDb.Set().Include(include).ToListAsync(); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return null; } } public async Task?> GetAllAsync(string include1, string include2) where TResult : class, IMetadata { try { return await gremlinDb.Set().Include(include1).Include(include2).ToListAsync(); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return null; } } public static async Task?> GetAllAsync(Predicate search) where TResult : class, IMetadata { ArgumentNullException.ThrowIfNull(search); try { return await Task.Run(() => gremlinDb.Set().AsEnumerable().Where(t => search(t)).ToList()); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return null; } } public async Task?> GetAllAsync(Predicate search, string include) where TResult : class, IMetadata { ArgumentNullException.ThrowIfNull(search); try { return await Task.Run(() => gremlinDb.Set().Include(include).AsEnumerable().Where(t => search(t)).ToList()); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return null; } } public static TResult? Get(Predicate search) where TResult : class, IMetadata, new() { try { return gremlinDb.Set().AsEnumerable().FirstOrDefault(t => search(t)); } catch (Exception e) { Console.WriteLine(e.InnerException); return null; } } public static async Task Get(Predicate search, string include1) where TResult : class, IMetadata, new() { ArgumentNullException.ThrowIfNull(search); try { return await Task.Run(() => gremlinDb.Set().Include(include1).AsEnumerable().First(t => search(t))); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return new(); } } public static async Task Get(Predicate search, string include1, string include2) where TResult : class, IMetadata, new() { ArgumentNullException.ThrowIfNull(search); try { return await Task.Run(() => gremlinDb.Set().Include(include1).Include(include2).AsEnumerable().First(t => search(t))); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return new(); } } public static async Task GetLastAsync() where TResult : class, IMetadata, new() { try { return await Task.Run(() => gremlinDb.Set().AsEnumerable().Last()); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return new(); } } public static int Insert(T entity) where T : class, IMetadata { try { gremlinDb.Set().Add(entity); return gremlinDb.SaveChanges(); } catch (DbUpdateException ex) { Console.WriteLine($"{ex.InnerException}"); HandleConcurrencyExceptions(ex); return -1; } catch (Exception exception) { Console.WriteLine(exception.InnerException); return 0; } } public static int Insert(IEnumerable entities) where T : class, IMetadata { // gremlinDb.Set().ToList(); //Get newest versions fresh from db try { gremlinDb.Set().AddRange(entities); return gremlinDb.SaveChanges(); } catch (DbUpdateException ex) { HandleConcurrencyExceptions(ex); return -1; } catch (Exception exception) { Console.WriteLine(exception.InnerException); return 0; } } public static async Task IsExistingAsync(Predicate search) where T : class, IMetadata { try { return await Task.Run(() => gremlinDb.Set().AsEnumerable().Any(t => search(t))); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return false; } } public static int Update(T entity) where T : class, IMetadata { try { gremlinDb.Set().Update(entity); return gremlinDb.SaveChanges(false); } catch (DbUpdateException ex) { HandleConcurrencyExceptions(ex); return -1; } catch (Exception exception) { Console.WriteLine(exception.InnerException); return 0; } } public static int Update(IEnumerable entities) where T : class, IMetadata { try { gremlinDb.Set().UpdateRange(entities); return gremlinDb.SaveChanges(); } catch (DbUpdateException ex) { HandleConcurrencyExceptions(ex); return -1; } catch (Exception exception) { Console.WriteLine(exception.InnerException); return 0; } } public static async Task RemoveAsync(T entity) where T : class, IMetadata { try { await Task.Run(() => gremlinDb.Set().Remove(entity)); return await gremlinDb.SaveChangesAsync(); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return 0; } } private static void HandleConcurrencyExceptions(DbUpdateException ex) { Console.WriteLine($"!!! HandleConcurrencyException: {ex.Message}"); foreach (EntityEntry entry in ex.Entries) switch (entry.Entity) { case Quote or CustomDescription or Account or Contact or Product: { PropertyValues proposedValues = entry.CurrentValues; PropertyValues? databaseValues = entry.GetDatabaseValues(); foreach (IProperty property in proposedValues.Properties) { object? proposedValue = proposedValues[property]; object? databaseValue = databaseValues[property]; // TODO: decide which value should be written to database // proposedValues[property] = <>; } // Refresh original values to bypass next concurrency check entry.OriginalValues.SetValues(proposedValues); break; } default: throw new NotSupportedException("Don't know how to handle concurrency conflicts for " + entry.Metadata.Name); } } public static async Task RemoveDublicatesAsync() where T : class, IMetadata { try { List entities = gremlinDb.Set().AsEnumerable().GroupBy(e => new { e.HashCode}).SelectMany(grp => grp.Skip(1)).ToList(); gremlinDb.Set().RemoveRange(entities); return await gremlinDb.SaveChangesAsync(); } catch (Exception exception) { Console.WriteLine(exception.InnerException); return 0; } } }