Reputation: 11351
We have a a number of logical domain objects that all reside in the same physical database table WorkStep
. A simple sample of the metadata in the sql table is
ID |NAME| TYPE
, such that TYPE
is a FK to a table that defines the types possible. However, once selected from the database each row might represent a different domain model, with VERY different business rules that must be applied. The business rule I am working with right now is that once created, the WorkStepType
property one of these objects can NEVER change. SO, any call to that would cause this this to change would be a very bad thing.
So, is it possible to make an object that can be constructed via add-ons like automapper, and dapper, that can have a property set once. and never changed? Also, the types can not be cast to each other.
I haven't tried much, I'm not even sure it is possible to do this without hacky code
Upvotes: 0
Views: 214
Reputation: 5692
Dapper maps to private properties (or private setters/mutators).
public class WorkStep
{
public WorkStepType WorkStepType { get; private set;}
}
If you need the resulting domain object to be a specific type, then just make the above class a simple factory that generates the type you are looking for.
public class WorkStepFactory
{
public WorkStepType WorkStepType { get; private set;}
public T CreateWorkStep<T>() where T : WorkStepBase{...}
}
Upvotes: 1
Reputation: 9
I see this as two separate operations.
The first would be to return a list of WorkStepType
objects available, the second would be to assign it as the immutable property on a "workflow" class exposing a generic type for your different objects.
Note - syntax is C#6. Not sure what the VB.NET equivalent would be.
Example
public class WorkStepType
{
// immutable properties
public int Id { get; }
public string Name { get; }
public WorkStepType(int id, string name)
{
this.Id = id;
this.Name = name;
}
}
And the generic class as
public class Workflow<T>
{
public WorkStepType WorkStep { get; }
public T DomainModel { get; }
public Workflow(WorkStepType type, T domainModel)
{
this.WorkStep = type;
this.DomainModel = domainModel;
}
}
How you choose to hydrate these objects is up to you. If you were using Drapper (built on top of Dapper) you might have a repository class that looked something like the below (although I'd advocate for separate CRUD repositories for WorkStepType/Workflows, this is to illustrate the idea)
public class WorkflowRepository
{
// IDbCommander is a Drapper construct.
private readonly IDbCommander _commander;
public WorkflowRepository(IDbCommander commander)
{
this._commander = commander;
}
public IEnumerable<WorkStepType> RetrieveAllWorkSteps()
{
// return all the available workstep types available
// to the user/application
return _commander.Query<WorkStepType>();
}
public Workflow Retrieve(WorkStepType type)
{
// lookup the specific domain model for the supplied
// workstep type.
var domainModel = _commander.Query<Workflow>(new { id = type.Id }).SingleOrDefault();
return new Workflow(type, domainModel);
}
}
This approach should give you the behaviour you're looking for and prove to be highly testable as well.
You may want to have the domain model publicly settable depending on whether you intend to assign a new instance to an existing WorkStepType
. Not sure of your design/needs but I'm sure you get the gist.
Hope that helps.
Upvotes: 0