Preface Feb 2015 If you are still using Entity Framework EDMX, please do yourself a favor and checkout using Entity Framework Code First instead. The differ
You can create a partial class, separate from the EF generated class, to store the metadata in.
//Contact.cs - The original auto-generated file
[System.ComponentModel.DataAnnotations.MetadataType(typeof(ContactMetadata))]
public partial class Contact
{
public int ContactID { get; set; }
public string ContactName { get; set; }
public string ContactCell { get; set; }
}
//ContactMetadata.cs - New, seperate class
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
internal sealed class ContactMetadata
{
[Required(ErrorMessage = "Name is required.")]
[StringLength(5)]
public string ContactName;
}
This has been answered correctly already, but I wanted to also add that I always find nesting the metadata seemed a bit cleaner to me, IMHO.
[MetadataType(typeof(ProductDescription.Metadata))]
public partial class ProductDescription
{
sealed class Metadata
{
[Key]
public long id { get; set; }
[Display(Name = "Title")]
public string title { get; set; }
// ...
}
}
I also noticed an added benefit of keeping the Metadata private to the class. The attribute will only work on the correct class, preventing a bug that may occur if you duplicate the class (to create a similar one). The bug can occur if you forget to change the class name in the attribute when renaming the duplicated class.
I know this has been marked answered but I want to clear some stuffs up.
@SteveCav said: "This member is defined more than once". I had the same exact same error. Spent hours trying to figure out.
To finally correct it, you have to create a separate file class in the same Assembly(I think this is already mentioned here). But what I want to stress is that this class should be nested with a partial class representing the Inner Class.
And then you decorate that inner class with the Annotation class. Like this:
//ContactMap.cs - Present in the same namespace as Contact.cs
[System.ComponentModel.DataAnnotations.MetadataType(typeof(ContactMap))]
partial class Contact // Present in the ContactMap class. This represent the Inner Class
{
}
//ContactMap.cs - This represent the outer class
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public class ContactMetadata
{
[Required(ErrorMessage = "Name is required.")]
[StringLength(5)]
public string ContactName;
}
Hope this is clearer or more understandable.
There is a variation of the suggested answers here that allows you to use classes in different assemblies and namespaces. I haven't actually tested it with EF, but I am using this for Swagger codegen API model classes.
In a nutshell: inherit from the model class and add metadata on the inherited class. An added benefit is that with Swagger codegen you can use the API model directly without mapping and for initial forms you can use the protected default ctor.
[MetadataType(typeof(LocalAssemblyModelMetadata))]
public class LocalAssemblyModel : IO.Swagger.Model.OtherAssemblyModel
{
public LocalAssemblyModel() : base () { }
}
public sealed class LocalAssemblyModelMetadata
{
[Required(ErrorMessage = "BaseclassProperty is mandatory.")]
public string BaseclassProperty { get; set; }
}
Mason240 answer works well, I will try to improve it : you could create a new ContactDataAnnotations.cs class with :
//ContactDataAnnotations.cs - A new file
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(ContactMetadata))]
public partial class Contact
{
// No field here
}
internal sealed class ContactMetadata
{
[Required(ErrorMessage = "Name is required.")]
[StringLength(5)]
public string ContactName {get; set; }
}
This way, you can regenerate your Contact class through EF without touching DataAnnotations - and without warning, by the way.