NHibernate can be extended with new implementations of IUserType, so I can customize how a mapped property is read and stored to/from the database.
An example. If I want DB null varchar to load as "n/a" string, and "n/a" string to be stored as null.
How is this possible with EF 6.2?
I am looking for a solution that doesn't break the change-tracker.
As of EF 6.2, there is no such functionality provided out of the box by the library.
If you decide to move to EF Core instead, there you can use the HasConversion
functionality.
However, in your case you still wouldn't be able to use it, because there is one caveat: it can't be used to convert null values. Null always gets converted to null. From docs:
A null value will never be passed to a value converter. A null in a database column is always a null in the entity instance, and vice-versa. This makes the implementation of conversions easier and allows them to be shared amongst nullable and non-nullable properties. See GitHub issue #13850 for more information.
In that case, I suggest that instead of a Value Conversion you configure your string property to have a Backing Field. Then, you can read/write to/from the private backing field, and then have a public property handling the null value.
public class Blog
{
private string _stringFromDb;
public string MyString { get; set; }
[BackingField(nameof(_stringFromDb))]
public string MyString
{
get { return _stringFromDb ?? "n/a"; }
}
public void SetMyString(string myString)
{
// put your validation code here
_stringFromDb = myString;
}
}
In EF 6.2 the closest you could have, as a workaround, is a [NotMapped]
property that can be in charge of translating the property you load from the DB.
public string StringDB { get; set; }
[NotMapped]
public string StringConverted
{
get { return MyStringProperty ?? "n/a"; }
set { MyStringProperty = value }
}
If, in addition to this, you want to hide the property being mapped to your DB by making it private
, it's not as straightforward as with EF Core's backing field, but you could follow this other answer for instructions on how to achieve it.