在实体POCO中使用自定义数据类型?

时间:2011-09-23 15:44:47

标签: c# entity-framework-4.1 poco

我有一个业务对象,比如UserUser有一个PhoneNumber字段,由字符串表示。我出于最好的理由,创建了一个隐含于/来自字符串运算符的PhoneNumber类。我是否必须做一些特殊的事情才能将PhoneNumber作为字符串写入数据库?现在,实体决定将我的PhoneNumber课程分解为其组成部分(AreaCodePrefix等),并将这些课程单独保存到数据库中。 PhoneNumber存储在单独的程序集中。

public class PhoneNumber : IEquatable<PhoneNumber>, IComparable<PhoneNumber>
{
    public static implicit operator string (PhoneNumber ph)
    {
        return ph.ToString ();
    }

    public static implicit operator PhoneNumber (string number)
    {
        return Parse(number);
    }

    public static PhoneNumber Parse(string number)
    {
       // ...
    }

    public override string ToString ()
    {
        // produce a Parse-compatible output
    }
}

public class User
{
    public virtual int Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual PhoneNumber Phone { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<User> Users { get; set; }
}

2 个答案:

答案 0 :(得分:3)

唯一的方法是这样的解决方法:

// You want to store in same table and not a navigation property, right?
// Then you need [ComplexType]
[ComplexType] 
public class PhoneNumber : IEquatable<PhoneNumber>, IComparable<PhoneNumber>
{
    // ...

    public string FullNumber
    {
        get
        {
            return Prefix + "-" + AreaCode + " " + Number; // or whatever
        }
        set
        {
            AreaCode = ParseToAreaCode(value); // or so...
            Prefix = ParseToPrefix(value);     // or so...
            Number = ParseToNumber(value);     // or so...
        }
    }

    [NotMapped]
    public string AreaCode { get; set; }
    [NotMapped]
    public string Prefix { get; set; }
    [NotMapped]
    public string Number { get; set; }
}

这样,您只能获得数据库中的FullNumber列。

答案 1 :(得分:3)

如果你的设计的其余部分允许它,你可以让PhoneNumber类离开映射,让User处理它的字符串表示,如:

public class User
{
  public virtual int Id { get; set; }
  public virtual string FirstName { get; set; }

  public virtual string PhoneNumber
  { 
      get { return this.PhoneNumber.ToString(); } // TODO: check for null
      set { this.PhoneNumber = PhoneNumber.Parse(value); }
  }

  [NotMapped]
  public virtual PhoneNumber Phone { get; set; }
}