2011-09-23 105 views
0

我有一个业务对象,说一个User。 A User有一个PhoneNumber字段,它由一个字符串表示。我出于最好的理由创建了一个PhoneNumber类,它隐含于/来自字符串运算符。我是否必须做任何特别的事情才能让PhoneNumber写成数据库的字符串?目前,Entity已决定将我的PhoneNumber课程分为几个组成部分(AreaCodePrefix等),并将其分别保存到数据库中。 PhoneNumber存储在一个单独的程序集中。在实体POCO中使用自定义数据类型?

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; } 
} 
+0

的EntityFramework正常工作把你的实体类和将每个属性表示为列。 PhoneNumber类是否是部分的,如果是这样的话,您可以在PhoneNumber类的非生成部分中覆盖您的ToString()。这样,无论它如何存储在数据库中,对象可以为您提供这些信息都无关紧要。 –

+0

它不是一个部分类,但该对象覆盖了ToString()并产生了我期望的结果。我会更新一些示例代码。 –

+0

好吧,所以我想这个问题是,为什么你想要存储为一个字符串,而不是实体表示形式的电话号码。 EF总是会将属性转换为列或属性,具体取决于您是否先执行代码。 –

回答

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

+0

这就是我所需要的,实际上让我为电话号码添加打包格式。非常感激! –

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; } 
} 
+0

这是一个同样可行的解决方案。我正在和Slauma一起,因为我想让PhoneNumber本身更加可重用,但是有很多情况下这种模式对我来说很有用。 –