Can WCF Code First DataServices return a NotMapped property?

1.9k views Asked by At

I'm using WCF Data Services for a RESTful API that returns a JSON response.

consider this object:

[Table("person")]
public class Person
{
    [Column("dob", TypeName = "datetime")]
    public DateTime DateOfBirth { get; set; }

    [NotMapped]
    public int Age
    {
        get { return CalculateAge(); }
        set { }
    }
}

WCF does not treat this object as I would expect. My service request completely ignores the Age property in the serialization of the Person object.

I've been using a workaround where I map the Age property to a dummy database column and I create a setter that does nothing. What an ugly hack! Is there a better way to have a DataService return a property that is not mapped to a database column?

4

There are 4 answers

1
codemonkey On BEST ANSWER

After much research, and no evidence to the contrary on stackoverflow, i'm going to go ahead and say the answer is: No. A WCF DataService with entities mapped using EntityFramework 4 can NOT return unmapped properties.

The ugly hack i've been using is this one, which requires you to acutally make a field in the database that just never gets read.

[Table("person")]
public class Person
{
    [Column("dob", TypeName = "datetime")]
    public DateTime DateOfBirth { get; set; }

    [Column("dummy1", TypeName = "int")]
    public int Age
    {
        get { return CalculateAge(); }
        set { }
    }
}
2
TheRealTy On

You may need to use the System.Runtime.Serialization attributes as these are what WCF will look at.

Not sure if you can have logic in your data contracts though.

[Table("person")]
[DataContract]
public class Person
{
    [Column("dob", TypeName = "datetime")]
    [DataMember]
    public DateTime DateOfBirth { get; set; }

    [NotMapped]
    [DataMember]
    public int Age
    {
        get { return CalculateAge(); }
    }
}

EDIT:

May need private setter (How do you configure a get-only property for a Silverlight-enabled WCF service)

0
AlexVPerl On

Here's what I used in those situations, similar to what is stated by tyrongower:

NOTE: this works with WCF and REST WCF as well as with JSON

[DataContract]
public class Submission
{
    [NotMapped]
    [DataMember]
    public string Location
    {
        get { return ""; }
        set { }
    }
}
1
Pakman On

I too hit this snag and decided to use extension methods. For example:

public static class PersonExtensions
{
    public static int GetAge(this Person person)
    {
        // your CalculateAge logic (simplified)
        return (DateTime.Now - person.DateOfBirth).TotalDays / 365;
    }
}

Then, in your DataServices consumer, you can do:

person.GetAge()

Yeah, it's not as nice as person.Age, but you're also not adding unnecessary database columns.

Update:

Another alternative is to extend the Person class contained in the service reference. You can do this by creating a partial Person class with the same namespace as the service reference Person class. For example:

public partial class Person
{
    public string int Age
    {
        get { return (DateTime.Now - this.DateOfBirth).TotalDays / 365; }
    }
}

Then the DataServices Person model will have the Age property!