Can WCF Code First DataServices return a NotMapped property?
-
22-04-2021 - |
Question
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?
Solution
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 { }
}
}
OTHER TIPS
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 { }
}
}
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)
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!