simplified version using subtype DAL instead of multiple. aggregate class no longer needed, but requires virtual methods for add/update
This commit is contained in:
parent
fef89fb923
commit
2405ae8d0e
@ -1,52 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace BinaryDad.AggregateDal
|
|
||||||
{
|
|
||||||
public class AggregateDataAccess<T> where T : class
|
|
||||||
{
|
|
||||||
private static ICollection<Type> dataAccessTypes;
|
|
||||||
|
|
||||||
static AggregateDataAccess() => LoadInstances();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes a method for all instances of <typeparamref name="T"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TResult"></typeparam>
|
|
||||||
/// <param name="func"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected TResult Invoke<TResult>(Func<T, TResult> func)
|
|
||||||
{
|
|
||||||
var results = new List<TResult>();
|
|
||||||
|
|
||||||
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<T>);
|
|
||||||
|
|
||||||
// load all types except for 1) the interface itself, 2) any interface, and 3) is not implementing AggregateDataAccess<T>
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -46,7 +46,6 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AggregateDataAccess.cs" />
|
|
||||||
<Compile Include="Models\BaseModel.cs" />
|
<Compile Include="Models\BaseModel.cs" />
|
||||||
<Compile Include="SettlementAttempt\EFSettlementAttemptDataAccess.cs" />
|
<Compile Include="SettlementAttempt\EFSettlementAttemptDataAccess.cs" />
|
||||||
<Compile Include="SettlementAttempt\ISettlementAttemptDataAccess.cs" />
|
<Compile Include="SettlementAttempt\ISettlementAttemptDataAccess.cs" />
|
||||||
@ -54,7 +53,6 @@
|
|||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Models\SettlementAttempt.cs" />
|
<Compile Include="Models\SettlementAttempt.cs" />
|
||||||
<Compile Include="SettlementAttempt\QuickBaseSettlementAttemptDataAccess.cs" />
|
<Compile Include="SettlementAttempt\QuickBaseSettlementAttemptDataAccess.cs" />
|
||||||
<Compile Include="SettlementAttempt\SettlementAttemptDataAccess.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
|
15
Program.cs
15
Program.cs
@ -52,21 +52,10 @@ namespace BinaryDad.AggregateDal
|
|||||||
|
|
||||||
private static IContainer CreateContainer()
|
private static IContainer CreateContainer()
|
||||||
{
|
{
|
||||||
/* NOTES:
|
|
||||||
* The StructureMap container will drive the instances of the DALs that will be invoked.
|
|
||||||
* DALs that inherit from AggregateDataAccess<T> 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<T>()
|
|
||||||
* 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 =>
|
return new Container(c =>
|
||||||
{
|
{
|
||||||
// when both DALs are needed (SQL and QuickBase)
|
// when saving to QuickBase is needed (as well as SQL)
|
||||||
c.For<ISettlementAttemptDataAccess>().Singleton().Use<SettlementAttemptDataAccess>();
|
c.For<ISettlementAttemptDataAccess>().Singleton().Use<QuickBaseSettlementAttemptDataAccess>();
|
||||||
|
|
||||||
// when only SQL is needed
|
// when only SQL is needed
|
||||||
//c.For<ISettlementAttemptDataAccess>().Singleton().Use<EfSettlementAttemptDataAccess>();
|
//c.For<ISettlementAttemptDataAccess>().Singleton().Use<EfSettlementAttemptDataAccess>();
|
||||||
|
@ -5,7 +5,7 @@ namespace BinaryDad.AggregateDal
|
|||||||
{
|
{
|
||||||
public class EFSettlementAttemptDataAccess : ISettlementAttemptDataAccess
|
public class EFSettlementAttemptDataAccess : ISettlementAttemptDataAccess
|
||||||
{
|
{
|
||||||
public bool AddAttempt(SettlementAttempt attempt)
|
public virtual bool AddAttempt(SettlementAttempt attempt)
|
||||||
{
|
{
|
||||||
// 1. create attempt in SQL using entity framework
|
// 1. create attempt in SQL using entity framework
|
||||||
// 2. update the "Id" property/PK of attempt upon insertion
|
// 2. update the "Id" property/PK of attempt upon insertion
|
||||||
|
@ -3,10 +3,13 @@ using System;
|
|||||||
|
|
||||||
namespace BinaryDad.AggregateDal
|
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)
|
// 1. create attempt in QuickBase ("Id" SQL PK should already be populated)
|
||||||
// 2. update the "RecordId" property/PK of attempt upon insertion
|
// 2. update the "RecordId" property/PK of attempt upon insertion
|
||||||
// 3. return if operation is successful
|
// 3. return if operation is successful
|
||||||
@ -18,8 +21,5 @@ namespace BinaryDad.AggregateDal
|
|||||||
|
|
||||||
return true;
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
using BinaryDad.AggregateDal.Models;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace BinaryDad.AggregateDal
|
|
||||||
{
|
|
||||||
public class SettlementAttemptDataAccess : AggregateDataAccess<ISettlementAttemptDataAccess>, ISettlementAttemptDataAccess
|
|
||||||
{
|
|
||||||
public bool AddAttempt(SettlementAttempt attempt) => Invoke(d => d.AddAttempt(attempt));
|
|
||||||
public SettlementAttempt GetAttempt(int recordId) => Invoke(d => d.GetAttempt(recordId));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user