Entity Framework 6 Code First - Custom Type Mapping
Asked Answered
L

1

7

I'm using some models inside my domain which are not very serialization- or mapping-friendly, such as structs or classes from the System.Net.* namespace.

Now I'm wondering if it's possible to define custom type mappings in Entity Framework.

Pseudo:

public class PhysicalAddressMap : ComplexType<PhysicalAddress>() {
    public PhysicalAddressMap() {

        this.Map(x => new { x.ToString(":") });
        this.From(x => PhysicalAddress.Parse(x));
    }
}

Desired result:

SomeEntityId       SomeProp         PhysicalAddress    SomeProp
------------------------------------------------------------------
           4          blubb       00:00:00:C0:FF:EE        blah

                                           ^
                                           |
                             // PhysicalAddress got mapped as "string"
                             // and will be retrieved by
                             // PhysicalAddress.Parse(string value)
Latia answered 24/3, 2014 at 23:13 Comment(0)
L
9

wrap a NotMapped property of type PhysicalAddress with a mapped string property that handles the conversions:

    [Column("PhysicalAddress")]
    [MaxLength(17)]
    public string PhysicalAddressString
    {
        get
        {
            return PhysicalAddress.ToString();
        }
        set
        {
            PhysicalAddress = System.Net.NetworkInformation.PhysicalAddress.Parse( value );
        }
    }

    [NotMapped]
    public System.Net.NetworkInformation.PhysicalAddress PhysicalAddress
    {
        get;
        set;
    }

Update: example code for comment asking about wrapping functionality in a class

[ComplexType]
public class WrappedPhysicalAddress
{
    [MaxLength( 17 )]
    public string PhysicalAddressString
    {
        get
        {
            return PhysicalAddress == null ? null : PhysicalAddress.ToString();
        }
        set
        {
            PhysicalAddress = value == null ? null : System.Net.NetworkInformation.PhysicalAddress.Parse( value );
        }
    }

    [NotMapped]
    public System.Net.NetworkInformation.PhysicalAddress PhysicalAddress
    {
        get;
        set;
    }

    public static implicit operator string( WrappedPhysicalAddress target )
    {
        return target.ToString();
    }

    public static implicit operator System.Net.NetworkInformation.PhysicalAddress( WrappedPhysicalAddress target )
    {
        return target.PhysicalAddress;
    }

    public static implicit operator WrappedPhysicalAddress( string target )
    {
        return new WrappedPhysicalAddress() 
        { 
            PhysicalAddressString = target 
        };
    }

    public static implicit operator WrappedPhysicalAddress( System.Net.NetworkInformation.PhysicalAddress target )
    {
        return new WrappedPhysicalAddress()
        {
            PhysicalAddress = target
        };
    }

    public override string ToString()
    {
        return PhysicalAddressString;
    }
}
Latham answered 24/3, 2014 at 23:48 Comment(7)
Is there any way to wrap this behaviour in a class to reuse it?Alden
Sure - create a complex type with relevant conversion operators. Added example code to solution.Latham
Ok, thanks. The problem I'm having right now is that I can't rename database columns because of backwards compatibility, so I'd want to map to a custom column each properties of type WrappedPhysicalAddressAlden
With attributes? (I don't like the fluent api)Alden
Yes and no - you can define the default column names with attributes, but if you want to change column names when used in a specific entity, you will need to use the fluent API. Try testing it out yourself next time.Latham
I've spent hours testing different possibilities. I'm asking to get answers to whether EF supports something like that.Alden
Does not support almost any EF Expression Tree.Valuer

© 2022 - 2024 — McMap. All rights reserved.