在域类中约束字符串长度

时间:2010-01-26 11:44:44

标签: c# string domain-model

我有一个持久性无知域模型,它使用抽象存储库来加载域对象。 我的存储库(数据访问层(DAL))的具体实现使用实体框架从sql server数据库中获取数据。 数据库对其许多varchar列具有长度限制。 现在假设我有以下域类:

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; }
}

抽象存储库定义如下:

public abstract class CaseRepository
{
    public abstract void CreateCase(Case item);
    public abstract Case GetCaseById(int id);
}

sqlserver中表的[text]列定义为nvarchar(100)

现在我知道我提到我的域类(Case)是持久性无知的,但我觉得它允许它是错误的 对于text参数的值,由于实体框架,我的具体存储库实现最终无法保存这些值 将text属性分配给实体框架生成的类时,如果它超过100个字符,则会抛出异常。 所以我决定在域模型中检查这个约束,因为这允许我在尝试之前检查数据有效性 将其传递给DAL,从而使错误报告更加中心到域对象。我想你可以说我可以检查一下 我的构造函数和属性setter中的约束,但由于我有数百个类都有类似的约束,我想要一个 更通用的方法来解决问题

现在,我提出的是一个名为ConstrainedString的类,定义如下:

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;
        } 
    }
}

此外,我的ConstrainedString实施名为String100

public class String100 : ConstrainedString
{
    public String100(string textValue) : base(100, textValue) { }
}

因此导致Case的不同实现看起来像这样:

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; }
}

现在,我的问题是;我是否可以忽略一些内置类或其他可以使用的方法?或者这是一种合理的方法吗?

欢迎任何意见和建议。

提前谢谢

3 个答案:

答案 0 :(得分:1)

我相信您的验证应该存在于您的域模型中。对字段的约束直接表示一些业务逻辑。最后,你必须在坚持之前进行验证。

答案 1 :(得分:0)

我认为这取决于很多因素(以及一些个人偏好)。有时,约束应该构成域对象的一部分 - 例如,使用社会安全号码/护照号码...... - 这些通常具有固定长度,不能作为域规则变化 - 不是数据持久性规则(尽管您可能会约束数据库)同样)。

有些人更喜欢在他们的域模型中没有这种检查,而是在属性上有类似的验证属性,可以通过单独的验证器从域对象外部检查和执行。

你的方法可能遇到的问题(尽管不难解决)是获取任何ORM / Mapper - 如果你正在使用它 - 知道如何将字符串映射到数据库或从数据库映射到ConstrainedString。 / p>

ConstrainedString可能无法解决域对象有关于约束的额外信息的问题,因为它可能需要构造ConstrainedString

答案 2 :(得分:0)

如果你改变一个案例的约束条件,那么你必须创建一个新案例 - 你已经改变了合同,旧代码将不再知道它是否符合要求。

不要担心您的存储库将允许或不允许的内容,而是定义将允许在您的类中使用的内容,并确保您找到一种方法来处理您更改到的任何存储库未来。您拥有自己的API - 您的依赖关系不会。