Few days back, I upgraded a Silverlight 3 RIA application to Silveright 4 bits. Once I fixed all the errors, it appeared that RIA generated entities were “over-validating” themselves. I noticed that all the string entities that were marked not-nullable in database were giving validation errors saying "Field XYZ is required". I looked through the attribute metadata classes and those field were not marked Required. However, the generated RIA classes had Required and StringLength attributes automatically applied on such fields. It looks RIA code generation is over-efficient and it automatically adds Required attributes for all non-nullable database fields. This doesn’t seem much problematic since we can easily write an implementation of the partial method OnCreated for our generated entities where we can assign default values to all fields. As a generic approach, we can write a reflective method that assign default values like this:
public static void SetDefaults(object obj)
{
DateTime defaultDate = new DateTime(1753, 1, 1);
PropertyInfo[] infos = obj.GetType().GetProperties();
foreach (PropertyInfo info in infos)
{
if (info.CanWrite)
{
//numeric fields (int, double etc) are already defaulted to 0
//string
if (info.PropertyType == typeof(string))
info.SetValue(obj, string.Empty, null);
//date fields
else if (info.PropertyType == typeof(DateTime))
info.SetValue(obj, defaultDate, null);
//timestamps
else if (info.PropertyType == typeof(byte[]))
info.SetValue(obj, new byte[1], null);
}
}
}
The above method needs to be called from the partial implementation of OnCreated for our generated data classes. However, things will still not work normally as there’s still a small point left: The Required attribute on string fields does not allow empty string. To tackle this, we need to decorate all our string fields in the metadata class (located in server project) with [Required(AllowEmptyString = true)]. That’s all.
April 28, 2011 at 2:35 PM
WCF RIA Service adding extra Required attribute on generated classes « Mehroz’s Experiments…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
May 6, 2011 at 2:01 AM
I don’t think it’s over efficient, I think it’s super efficient, and this is how it should work.
I just think they have to make it more obvious and even more efficient (for example managing the string length according to the one in the database etc.).
May 6, 2011 at 2:04 AM
And BTW, for value types (non-nullable types), you gain the default value in a more generic way: default(DateTime).
HTH
December 1, 2011 at 10:52 AM
What if column is a computed column such as timestamp? It will throw required validation error, and you won’t be able to assign default value because it is computed and readonly.
December 1, 2011 at 10:56 AM
Then if you set Nullable = False in EF designer then you will get an error 3301: non-nullable column mapped to a nullable column.