8

我有一个持久性无知的域模型,它使用抽象存储库来加载域对象。我的存储库(数据访问层 (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)

现在我知道我提到我的域Casetext(分配text超过 100 个字符时,实体框架生成的类的属性。所以我决定在域模型中检查这个约束,因为这允许我在尝试将数据传递给 DAL 之前检查数据的有效性,从而使错误报告更加集中于域对象。我想你可能会争辩说我可以只检查构造函数和属性设置器中的约束,但是由于我有数百个类都有类似的约束,我想要一种更通用的方法来解决问题

现在,我想出的是一个名为 的类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; }
}

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

欢迎任何意见和建议。

先感谢您

4

3 回答 3

1

我相信您的验证应该驻留在您的域模型中。字段上的约束直接代表一些业务逻辑。最终,您必须在坚持之前进行验证。

于 2010-02-17T03:14:53.570 回答
0

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

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

您的方法可能遇到的问题(尽管不难解决)是让任何 ORM/Mapper(如果您使用的是一个)来了解如何将字符串映射到/从 db 到您的 ConstrainedString。

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

于 2010-01-26T12:06:45.620 回答
0

如果您更改 Case 的约束,那么您必须创建一个新的约束是有道理的——您已经更改了合同,旧代码将不再知道它是否满足要求。

不必担心您的存储库将允许或不允许什么,而是定义将在您的类中允许的内容,并确保您找到一种方法来处理您将来更改为的任何存储库。您拥有自己的 API - 您的依赖项不拥有。

于 2010-02-17T03:44:41.800 回答