I have a persistence ignorant domain model that uses abstract repositories to load domain objects. The concrete implementation of my repositories (the data access layer (DAL)) uses entity framework to fetch data from a sql server database. The database has length constraints on a lot of its varchar columns. Now imagine that I have the following domain class:
public class Case
{
public Case(int id, string text)
{
this.Id = id;
this.Text = text;
}
public int Id { get; private set; }
public string Text { get; set; }
}
And an abstract repository defined as follows:
public abstract class CaseRepository
{
public abstract void CreateCase(Case item);
public abstract Case GetCaseById(int id);
}
The [text]
column of the table in sqlserver is defined as nvarchar(100)
Now I know that I mentioned that my domain class (Case
) was persistence ignorant, nevertheless I feel that it is wrong that it allows
for values of the text
parameter that cannot ultimately be saved by my concrete repository implementation because the entity framework
will throw an exception when assigning the text
property to the entity framework generated class when it is longer than 100 characters.
So I have decided that I wish to check this constraint in the domain model, because this allows me to check data validity before attempting to
pass it on to the DAL, and thus making error reporting more centric to the domain object. I guess you could argue that I could just check the
constraint in my constructor and in the property setter, but since I have hundreds of classes that all have similar constraints I wanted a
more generic way to solve the problem
Now, the thing that I've come up with is a class called ConstrainedString
, defined as follows:
public abstract class ConstrainedString
{
private string textValue;
public ConstrainedString(uint maxLength, string textValue)
{
if (textValue == null) throw new ArgumentNullException("textValue");
if (textValue.Length > maxLength)
throw new ArgumentException("textValue may not be longer than maxLength", "textValue");
this.textValue = textValue;
this.MaxLength = maxLength;
}
public uint MaxLength { get; private set; }
public string Value
{
get
{
return this.textValue;
}
set
{
if (value == null)
throw new ArgumentNullException("value");
if (value.Length > this.MaxLength) throw new ArgumentException("value cannot be longer than MaxLength", "value");
this.textValue = value;
}
}
}
Furthermore I have an implementation of ConstrainedString
called String100
:
public class String100 : ConstrainedString
{
public String100(string textValue) : base(100, textValue) { }
}
Thus leading to a different implementation of Case
that would look like this:
public class Case
{
public Case(int id, String100 text)
{
this.Id = id;
this.Text = text;
}
public int Id { get; private set; }
public String100 Text { get; set; }
}
Now, my question is; Am I overlooking some built-in classes or some other approach that I could use instead? Or is this a reasonable approach?
Any comments and suggestions are most welcome.
Thank you in advance