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 EnsureCreatedAsync() { bool b = await gremlinDb.Database.EnsureCreatedAsync(); await gremlinDb.SaveChangesAsync(); return b; } public static async Task Migrate() { await gremlinDb.Database.MigrateAsync(); await gremlinDb.SaveChangesAsync(); } 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; } } public static async Task RemoveAsync(IList entities) where T : class, IMetadata { try { await Task.Run(() => gremlinDb.Set().RemoveRange(entities)); 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 or CustomDescription: { 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; } } }