Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 约束域类中的字符串长度_C#_String_Domain Model - Fatal编程技术网

C# 约束域类中的字符串长度

C# 约束域类中的字符串长度,c#,string,domain-model,C#,String,Domain Model,我有一个不知道持久性的域模型,它使用抽象存储库来加载域对象。 my repositories的具体实现(数据访问层(DAL))使用实体框架从sql server数据库获取数据。 数据库的许多varchar列都有长度限制。 现在假设我有以下域类: public class Case { public Case(int id, string text) { this.Id = id; this.Text = text; } pub

我有一个不知道持久性的域模型,它使用抽象存储库来加载域对象。 my repositories的具体实现(数据访问层(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);
}
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;
        } 
    }
}
sqlserver中表的
[text]
列定义为
nvarchar(100)

现在我知道我提到我的域类(
Case
)是不知道持久性的,但是我觉得它允许持久性是错误的 对于
text
参数的值,由于实体框架 将
text
属性指定给实体框架生成的类时,如果该类的长度超过100个字符,将引发异常。 因此,我决定在域模型中检查这个约束,因为这允许我在尝试创建之前检查数据的有效性 将其传递给DAL,从而使错误报告更加以域对象为中心。我想你会说我可以检查一下 约束在构造函数和属性设置器中,但由于我有数百个类都具有类似的约束,所以我需要一个 更通用的解决问题的方法

现在,我想到了一个名为
ConstrainedString
的类,定义如下:

public abstract class CaseRepository
{
    public abstract void CreateCase(Case item);
    public abstract Case GetCaseById(int id);
}
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;
        } 
    }
}
此外,我还有一个名为
String100
ConstrainedString
实现:

public class String100 : ConstrainedString
{
    public String100(string textValue) : base(100, textValue) { }
}
因此导致了一个不同的
案例
实现,如下所示:

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; }
}
现在,我的问题是;我是否忽略了一些内置类或其他我可以使用的方法?或者这是一个合理的方法

欢迎提出任何意见和建议


提前谢谢

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

有些人不希望在他们的域模型中有这样的检查,而是希望在属性上有类似于验证属性的东西,这些属性可以由单独的验证器从域对象外部检查和执行

您的方法可能存在的问题(虽然不难找到)是让任何ORM/Mapper(如果您使用的是ORM/Mapper)知道如何将字符串映射到db或从db映射到ConstrainedString


ConstrainedString可能无法解决域对象具有关于约束的额外信息的问题,因为它可能需要构造ConstrainedString。我认为验证应该驻留在域模型中。字段上的约束直接表示一些业务逻辑。最终,您必须在坚持之前进行验证。

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


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

+1个好问题—我经常想知道为什么BCL中不存在这样的类型。然而,我认为它有一种泄漏的抽象的味道,即你让关系数据库像那样影响域模型,或者这些约束有一个令人信服的域原因吗?@markseemann我同意你的看法,它有一种气味,而且大多数情况下,约束没有令人信服的域原因。基本上,它是一个遗留数据库模式,可能会从一些重构中受益,但这超出了我们当前的范围。但无论如何,我不认为我可以忽略模型中的这些约束,因为我想让数据验证成为模型的一部分,而不是存储库实现的一部分(我认为这是一个公平的目标)啊,遗留应用程序的奇妙世界。。。请考虑为实现这些约束的域模型创建一个装饰层,以保持您的域模型干净。请参阅此处了解更多详细信息:2D00-Bug\U 2D00\U 2D00\U Bug-Compatibility.aspx