Bind custom class to a column in database with EF 4 POCO
I have create a class, let's call it User. In this class I have a custom created class called EMail. This class contains only a string that holds the value of the emailadress and some logic to verify the address. So it looks like this in my User class.
public class User{
public string Name{get;set;}
public EMailAddress EMail{get;set;}
...
}
I now want to bind this EMail to a column in my databas by using EF4's CTP5 code. But I can't do this, I don't even get an good exception back, all I get is "Thread aborted exception", but if I comment out my EMail property it works good.
My EMailAddress class looks like this.
public class EMailAddress
{
//-- Declaration
private string _email;
//-- Constructor
public EMailAddress(string emailAddress)
{
if (emailAddress == null)
throw new ArgumentNullException(string.Format("Supplied emailaddress can't be null"));
if (!IsValid(emailAddress))
throw new ArgumentException(string.Format("'{0}' is not a valid Emailaddress", emailAddress));
_email = emailAddress;
}
//-- Methods
private stat开发者_运维百科ic bool IsValid(string emailAddress)
{
Regex re = new Regex(Constants.EMAIL_REGULAR_EXPRESSION_PATTERN);
return re.IsMatch(emailAddress);
}
public override string ToString()
{
return _email;
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (obj is string)
return _email == (string)obj;
if(obj is EMailAddress)
return _email == ((EMailAddress)obj).ToString();
return false;
}
public override int GetHashCode()
{
return _email.GetHashCode();
}
//-- Operator
public static bool operator ==(EMailAddress emailAddress, EMailAddress emailAddress2)
{
return object.Equals(emailAddress, emailAddress2);
}
public static bool operator !=(EMailAddress emailAddress, EMailAddress emailAddress2)
{
return !(emailAddress == emailAddress2);
}
}
And I want to keep my EMailAddress class free of any public properties. Is there a way to let the EF use the .ToString() method when itsaves the value to the database, and use the constructor when loading the data from the database to populate my objects.
Thanks...
No it is not possible. You have two choices:
- Add another string property to your User class. This property will be responsible for returning email and setting email (creating EmailAddress instance). This property will be mapped. Add
[NotMappedAttribute]
to EMail property. You can play with visibility of the new property. In common EF you can change visibility of property but I'm not sure if it is also possible in code-first. - Map EMailAddress as complex type (mark it with
[ComplexTypeAttribute]
but in such case you again need to add string property to EMailAddress.
You can map non-public properties to columns in EF but the default codefirst API doesn't support it out of the box. I've made some free code available that you can use in your projects to support this need. You'll still have to have the properties but they can be protected or private or internal now.
Details are here http://blogs.msdn.com/b/schlepticons/archive/2011/08/31/map-private-properties-with-ef-fluent-api.aspx
精彩评论