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

本文关键字:定义数据类型 实体 poco | 更新日期: 2023-09-27 18:09:26

我有一个业务对象,比如UserUser有一个PhoneNumber字段,用字符串表示。出于最好留给我的原因,我创建了一个PhoneNumber类,它具有隐式的to/from字符串操作符。我是否需要做任何特别的事情来获得PhoneNumber作为字符串写入数据库?现在,实体已经决定把我的PhoneNumber类分解成它的组成部分(AreaCode, Prefix等),并将它们单独保存到数据库中。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; }
}

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

唯一的解决方法是:

// 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列。

如果您的其余设计允许,您可以将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; }
}