From 2405ae8d0e9649f3981818dc1574e2cc461f00e3 Mon Sep 17 00:00:00 2001 From: Ryan Peters Date: Tue, 15 Sep 2020 19:24:48 -0400 Subject: [PATCH] simplified version using subtype DAL instead of multiple. aggregate class no longer needed, but requires virtual methods for add/update --- AggregateDataAccess.cs | 52 ------------------- BinaryDad.AggregateDal.csproj | 2 - Program.cs | 15 +----- .../EfSettlementAttemptDataAccess.cs | 2 +- .../QuickBaseSettlementAttemptDataAccess.cs | 10 ++-- .../SettlementAttemptDataAccess.cs | 11 ---- 6 files changed, 8 insertions(+), 84 deletions(-) delete mode 100644 AggregateDataAccess.cs delete mode 100644 SettlementAttempt/SettlementAttemptDataAccess.cs diff --git a/AggregateDataAccess.cs b/AggregateDataAccess.cs deleted file mode 100644 index a17c66d..0000000 --- a/AggregateDataAccess.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace BinaryDad.AggregateDal -{ - public class AggregateDataAccess where T : class - { - private static ICollection dataAccessTypes; - - static AggregateDataAccess() => LoadInstances(); - - /// - /// Invokes a method for all instances of - /// - /// - /// - /// - protected TResult Invoke(Func func) - { - var results = new List(); - - foreach (var dataAccessType in dataAccessTypes) - { - var instance = Activator.CreateInstance(dataAccessType) as T; - - results.Add(func(instance)); - } - - // if the "EF" version invokes first, return that value - return results.FirstOrDefault(r => !r.Equals(default(T))); - } - - private static void LoadInstances() - { - if (dataAccessTypes == null) - { - var type = typeof(T); - var aggregateType = typeof(AggregateDataAccess); - - // load all types except for 1) the interface itself, 2) any interface, and 3) is not implementing AggregateDataAccess - // NOTE: the "EF" version will load first, allowing for the "QuickBase" version to run last, in a separate thread if desired - dataAccessTypes = Assembly.GetExecutingAssembly() - .ExportedTypes - .Where(t => type.IsAssignableFrom(t) && !t.IsInterface && !aggregateType.IsAssignableFrom(t)) - .OrderBy(t => t.Name.StartsWith("QuickBase", StringComparison.OrdinalIgnoreCase)) - .ToList(); - } - } - } -} diff --git a/BinaryDad.AggregateDal.csproj b/BinaryDad.AggregateDal.csproj index e051e7f..1882bb1 100644 --- a/BinaryDad.AggregateDal.csproj +++ b/BinaryDad.AggregateDal.csproj @@ -46,7 +46,6 @@ - @@ -54,7 +53,6 @@ - diff --git a/Program.cs b/Program.cs index cd1d7e4..04c0913 100644 --- a/Program.cs +++ b/Program.cs @@ -52,21 +52,10 @@ namespace BinaryDad.AggregateDal private static IContainer CreateContainer() { - /* NOTES: - * The StructureMap container will drive the instances of the DALs that will be invoked. - * DALs that inherit from AggregateDataAccess will automatically aggregate types implementing T - * and will invoke them. This means we can have implementations of QuickBaseXxxDataAccess and - * EfXxxDataAccess that focus solely on their own operations. Once we decide to turn off a feature - * (i.e., we no longer need to save to QB for a particular DAL), we can change the .Use() - * to use a regular EfXxxDataAccess instance. - * - * NO OTHER PARTS OF THE CODEBASE WOULD NEED TO BE TOUCHED, as we're only changing the instance - * of a DAL from an aggregate to a singular instance */ - return new Container(c => { - // when both DALs are needed (SQL and QuickBase) - c.For().Singleton().Use(); + // when saving to QuickBase is needed (as well as SQL) + c.For().Singleton().Use(); // when only SQL is needed //c.For().Singleton().Use(); diff --git a/SettlementAttempt/EfSettlementAttemptDataAccess.cs b/SettlementAttempt/EfSettlementAttemptDataAccess.cs index 959a696..264f765 100644 --- a/SettlementAttempt/EfSettlementAttemptDataAccess.cs +++ b/SettlementAttempt/EfSettlementAttemptDataAccess.cs @@ -5,7 +5,7 @@ namespace BinaryDad.AggregateDal { public class EFSettlementAttemptDataAccess : ISettlementAttemptDataAccess { - public bool AddAttempt(SettlementAttempt attempt) + public virtual bool AddAttempt(SettlementAttempt attempt) { // 1. create attempt in SQL using entity framework // 2. update the "Id" property/PK of attempt upon insertion diff --git a/SettlementAttempt/QuickBaseSettlementAttemptDataAccess.cs b/SettlementAttempt/QuickBaseSettlementAttemptDataAccess.cs index 5d0ee3f..8535301 100644 --- a/SettlementAttempt/QuickBaseSettlementAttemptDataAccess.cs +++ b/SettlementAttempt/QuickBaseSettlementAttemptDataAccess.cs @@ -3,10 +3,13 @@ using System; namespace BinaryDad.AggregateDal { - public class QuickBaseSettlementAttemptDataAccess : ISettlementAttemptDataAccess + public class QuickBaseSettlementAttemptDataAccess : EFSettlementAttemptDataAccess { - public bool AddAttempt(SettlementAttempt attempt) + public override bool AddAttempt(SettlementAttempt attempt) { + // save to SQL first + base.AddAttempt(attempt); + // 1. create attempt in QuickBase ("Id" SQL PK should already be populated) // 2. update the "RecordId" property/PK of attempt upon insertion // 3. return if operation is successful @@ -18,8 +21,5 @@ namespace BinaryDad.AggregateDal return true; } - - // NOTE: we have no need to retrieve a record from QB, as it will come from SQL - public SettlementAttempt GetAttempt(int recordId) => null; } } diff --git a/SettlementAttempt/SettlementAttemptDataAccess.cs b/SettlementAttempt/SettlementAttemptDataAccess.cs deleted file mode 100644 index ff6696b..0000000 --- a/SettlementAttempt/SettlementAttemptDataAccess.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BinaryDad.AggregateDal.Models; -using System.Linq; - -namespace BinaryDad.AggregateDal -{ - public class SettlementAttemptDataAccess : AggregateDataAccess, ISettlementAttemptDataAccess - { - public bool AddAttempt(SettlementAttempt attempt) => Invoke(d => d.AddAttempt(attempt)); - public SettlementAttempt GetAttempt(int recordId) => Invoke(d => d.GetAttempt(recordId)); - } -}