Note that there are some explanatory texts on larger screens.

plurals
  1. PONeed some help sorting out a major abstract pattern headache within my DAL
    text
    copied!<p>I've caused myself a bit of an issue with my Data Access Layer. In this particular instance, I have a table that contains potentially 5 types of 'entity'. These are basically Company, Customer, Site, etc. The type is dictated by a PositionTypeId within the table. They're all in the same table as they all havethe same data structure; <em>PositionId, Description and Code</em>.</p> <p>I have a main abstract class as follows:</p> <pre><code>public abstract class PositionProvider&lt;T&gt; : DalProvider&lt;T&gt;, IDalProvider where T : IPositionEntity { public static PositionProvider&lt;T&gt; Instance { get { if (_instance == null) { // Create an instance based on the current database type } return _instance; } } private static PositionProvider&lt;T&gt; _instance; public PositionType PositionType { get { return _positionType; } } private PositionType _positionType; // Gets a list of entities based on the PositionType enum's value. public abstract List&lt;T&gt; GetList(); internal void SetPositionType(RP_PositionType positionType) { _positionType = positionType; } } </code></pre> <p>I want to then be able to put all the general code within an inherting class that is either SQL or Oracle based. This is my SQL implementation:</p> <pre><code>public class SqlPositionProvider&lt;T&gt; : PositionProvider&lt;T&gt; where T : IPositionEntity { public override List&lt;T&gt; GetList() { int positionTypeId = (int)this.PositionType; using (SqlConnection cn = new SqlConnection(Globals.Instance.ConnectionString)) { SqlCommand cmd = new SqlCommand("Get_PositionListByPositionTypeId", cn); cmd.Parameters.Add("@PositionTypeId", SqlDbType.Int).Value = positionTypeId; cmd.CommandType = CommandType.StoredProcedure; cn.Open(); return this.GetCollectionFromReader(this.ExecuteReader(cmd)); } } } </code></pre> <p>I've then create a class for each type as follows (this is the CustomerProvider as an example):</p> <pre><code>public class CustomerProvider { public static PositionProvider&lt;CustomerEntity&gt; Instance { get { if ((int)PositionProvider&lt;CustomerEntity&gt;.Instance.PositionType == 0) { PositionProvider&lt;CustomerEntity&gt;.Instance.SetPositionType(PositionType.Customer); } return PositionProvider&lt;CustomerEntity&gt;.Instance; } } } </code></pre> <p>This all works fantastically... until I realised that I have certain functions that are related specifically to certain position types. I.e. I need to be able to get all Customers (which is an IPositionType) based on the user permissions.</p> <p>So I need to add another abstract method:</p> <pre><code>public abstract List&lt;CustomerEntity&gt; GetCustomersByUserPermission(Guid userId); </code></pre> <p>Now, obviously I don't want this within my PositionProvider abstract class as that would mean that method would appear when dealing with the site/company provider.</p> <p>How can I add this, and other, additional methods without having to duplicate the code within the SqlPositionProvider?</p> <p><strong>Edit:</strong></p> <p>The only idea I've come up with is to separate the PositionProvider out into a common property of the CustomerProvider, SiteProvider, etcProvider:</p> <pre><code>public abstract class CustomerProvider { public CustomerProvider() { this.Common.SetPositionType(PositionType.Customer); } public PositionProvider&lt;CustomerEntity&gt; Common { get { if (_common == null) { DalHelper.CreateInstance&lt;PositionProvider&lt;CustomerEntity&gt;&gt;(out _common); } return _common; } } private PositionProvider&lt;CustomerEntity&gt; _common; public static CustomerProvider Instance { get { if (_instance == null) { DalHelper.CreateInstance&lt;CustomerProvider&gt;(out _instance); } return _instance; } } private static CustomerProvider _instance; public abstract List&lt;CustomerEntity&gt; GetCustomersByUserPermission(Guid userId); } </code></pre> <p>This would allow me to put the specific code within <code>CustomerProvider.Instance.MyNonGenericMethod()</code>, and then to access the <code>PositionProvider</code> I could do <code>CustomerProvider.Instance.Common.GetList()</code>... This does seem like a bit of a hack though.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload