在使用像Entity Framework这样的ORM时如何处理原始的迷恋?

时间:2015-04-16 03:28:43

标签: c# entity-framework design-patterns orm primitive-types

我确实理解创建整个价值类来封装特定域名的好处。

但是当类/实体持久存储在数据库中时,如何处理它呢?

例如:

class User
{
   Email Email { get; set;}
   Address Address { get; set;}
   PhoneNumber CellPhone { get; set;}
   PhoneNumber HomePhone { get; set;}
}

要保留此数据的SQL表将包含标准类型(nvarchar);

的列

如果ORM从中生成类,它将看起来像

class User
{
   string Email { get; set;}
   string Address { get; set;}
   string CellPhone { get; set;}
   string HomePhone { get; set;}
}

所以,问题是,什么是允许使用整个值并消除原始迷恋的模式,但仍然使用原始类型存储它?你如何使ORM与它一起正常工作?

2 个答案:

答案 0 :(得分:3)

Primitive Obsession是与域层相关的主题,而不是与持久层相关的主题。当你的域中有User类时,Email应该表示为Value Object,但对于持久层,你不应该使用你的域对象,你需要有不同的User类,Email属性作为原始,然后使用Memento Pattern或自动映射库,如AutoMapper,用于填充持久性用户类并存储它。所有这些工作都应该由您的Generic / Specific Repository Class完成,因为存储库应该是关于持久性技术的抽象消费者。

Domain / User.cs

public class User {
   //code omitted for brevity
   public EmailAddress Email { get; set; } //or protected set?
}

Persistence / User.cs

public class User {
       //code omitted for brevity
       public string Email { get; set; }
}

存储库/ UserRepository.cs

public class UserRepository {

   //code omitted for brevity

   public void Save(Domain.User user) {
      //Pseudo-code
      //1) Validate Domain.User
      //2) Convert Domain.User to Persistence.User
      //3) Persist Persistence.User
   }
}

最后一条评论:如果您在EmailAddress类上使用重载转换运算符,则可以简化转换,因此您可以将其转换为字符串而不必过于担心它。

答案 1 :(得分:2)

实体框架设计器允许您设置从数据库列映射的属性的名称和可见性,因此您可以设置"基元"属性到private,然后声明执行转换的包装器属性。

粗略的例子:

// Class generated by entity framework designer
partial class User
{
    // Entity framework designer can be told to declare private properties
    // with custom "Db" names
    private string DbEmail { get; set; }      // Maps to Email column
    private string DbAddress { get; set; }    // Maps to Address column
    private string DbCellPhone { get; set; }  // Maps to CellPhone column
    private string DbHomePhone { get; set; }  // Maps to HomePhone column
}


// Class declared in User.cs
partial class User
{
    public Email Email
    {
        get { return new Email(DbEmail); }
        set { DbEmail = value.ToString(); }
    }

    public Address Address
    {
        get { return new Address(DbAddress); }
        set { DbAddress = value.ToString(); }
    }

    /* and so on...*/
}