How Do I Add Display Name To An Inherited Property With EF Code First? - entity-framework

I have a class Movement inheriting from TimeBlock. TimeBlock is provided for me and I can't change it. TimeBlock provides a DurationDescription property and I want to display it. However I always use LabelFor etc which means I need to have Display metadata on DurationDescription so I can have "Duration Desc." etc.
How do I add metadata to an inherited class with EF Code First. Am I supposed to use buddy metadata?

Yes, you need to use the MetadataTypeattribute. It will work fine also with inheritance like with partial classes:
public class Base
{
public string Prop1 { get; set; }
}
[MetadataType(typeof(ClassMetadata))]
public class Class : Base
{
[DisplayName("My prop 2")]
public string Prop2 { get; set; }
class ClassMetadata
{
[DisplayName("My prop 1")]
public string Prop1 { get; set; }
}
}
On the UI the properties will be displayed as "My prop 1" and "My prop 2".

Related

AutoMapper: Mapping objects with interface properties

my current task needs to pay attention on mapping between different object types and so I recognized the very nice AutoMapper library.
So far easy to handle but these different objects contains complex interface type properties. Let me show you a code snippet:
public inferface IInterface
{
string TextProperty { get; set;}
}
public class A : IInterface
{
string TextProperty { get; set; }
}
public class B : IInterface
{
string TextProperty { get; set; }
}
public inferface IComplexInterface
{
IInterface ComplexProperty { get; set; }
}
public class ComplexA : IComplexInterface
{
IInterface ComplexProperty { get; set; }
}
public class ComplexB : IComplexInterface
{
IInterface ComplexProperty { get; set; }
}
In my case it is possible that class A is mapped to class B and vice versa.
Mapping from type A to B is no problem by configuring CreateMap<A, B>();
Mapping from class ComplexA to class ComplexB throws an exception:
Error mapping types.
Mapping types:
ComplexA -> ComplexB
NamespaceOfComplexA.ComplexA -> NamespaceOfComplexB.ComplexB
Type Map configuration:
ComplexA -> ComplexB
NamespaceOfComplexA.ComplexA -> NamespaceOfComplexB.ComplexB
Property:
ComplexProperty
A possible solution I already found here on stackoverflow could be a configuration as follows:
CreateMap<A, IInterface>().As<B>();
CreateMap<B, IInterface>().As<A>();
But in my case it is not working.
Any suggestions?
Now, I found a solution that works for me.
I use AutoMapper with a non generic approach and so I configure via:
CreateMap(typeof(ComplexA), typeof(ComplexB))
To consider properties with complex types like interfaces or even abstract classes it is possible to write an own ValueResolver that has to implement the interface:
IValueResolver<object, object, object>
with following method:
public object Resolve(object source, object destination, object destMember, ResolutionContext context)
{
//...
}
To resolve interface/abstract class properties you can configure your types by enhancing the configuration with the method ForMember(...) and define a conrete ValueResolver for the particular property as follows:
CreateMap(typeof(ComplexA), typeof(ComplexB)).ForMember("ComplexProperty", x => x.ResolveUsing(new ValueResolver(/*...*/)));
In my case it was the solution to map the interface property to a concrete implementation of my class definitions.
Hope it is useful.

How to use AOP (PostSharp) for Serialization?

Is it possible to inject code to read/write the properties of an object using a PostSharp aspect? For example, consider the following class:
[ BinarySerializable ]
public class Employee {
public string Name {get; set; }
public string Title {get; set;}
}
In this case, "BinarySerializable" would be a custom aspect that introduces a custom "IBinarySerializable" interface, as follows:
public interface IBinarySerializable
{
void Write(BinaryWriter writer);
void Read(BinaryReader reader);
}
After compilation, the resulting class would look like this:
public class Employee : IBinarySerializable
{
public string Name {get; set;}
public string Title {get; set; }
void IBinarySerializable.Write(BinaryWriter writer)
{
writer.Write(Name);
writer.Write(Title);
}
void IBinarySerializable.Read(BinaryReader reader)
{
Name = reader.ReadString();
Title = reader.ReadString();
}
}
Intuitively, I feel this should be possible using PostSharp, but I need some direction as to the right approach. If this is possible, then how to handle properties that are themselves injected by some other aspect?
UPDATE: I tried creating a simple example using the built-in PSerializable aspect, but ran into problems when members inherit from .NET framework classes that do not have that attribute.
Adding the [PSerializable] attribute to the EmployeeCollection class fails to compile with "Cannot apply [PSerializable] to type 'AOPSerialization.EmployeeCollection' because the base type does not have a [PSerializable] or [Serializer] attribute."
Omitting the [PSerializable] attribute from the EmployeeCollection class throws a runtime PortableSerializationException: Cannot find a serializer for type 'AOPSerialization.EmployeeCollection'.
For example:
[PSerializable]
public class AOPComponent
{
public string Title { get; set; }
public string Description { get; set; }
public AOPComponent(string title, string description){...}
}
[PSerializable]
public class AOPComponentCollection<T> : ObservableCollection<T>
{...}
[PSerializable]
public class EmployeeCollection : AOPComponentCollection<Employee>
{...}
[PSerializable]
public class Company : AOPComponent
{
public EmployeeCollection Engineers { get; set; }
public EmployeeCollection Managers { get; set; }
}
I figured out that the Serializer and ImportSerializer attributes are used to tell the PortableFormatter which custom ISerializer or ISerializerFactory implementation to use.
But the question remains:
How to specify a custom serializer for the generic base collection type?
This approach fails because an attribute may not include type parameters.
[PSerializable, ImportSerializer(typeof(ObservableCollection<T>), typeof(AOPComponentSerializerFactory))]
public class AOPComponentCollection<T> : ObservableCollection<T> where T : AOPComponent
{...}
This approach fails because PostSharp cannot find a serializer for ObservableCollection< T >
[PSerializable, Serializer(typeof(AOPComponentSerializerFactory))]
public class AOPComponentCollection<T> : ObservableCollection<T> where T : AOPComponent
{...}
It would be possible to do that with PostSharp, but only by using the low-level PostSharp SDK, which is undocumented and unsupported.
Good news are that we already implemented this for you, in the namespace PostSharp.Serialization. The aspect is [PSerializable] and the formatter is PortableFormatter.

ef5 database first data annotation

I am starting MVC4 with VS2012. I am also using EF5 with the "Database First" method of creating my classes.
However because the generated glasses can be regenerated I cannot put the Data Annotation details to assist with validation.
I have seen some code snippets that use MetaData and partial classes but I was wondering if anyone knows of a small compilable example that I can look at and pull apart to better understand how the vasious classes interlink.
Many many thanks for any help.
Dave
You can achieve what you need through extending models. Suppose that EF generated the following entity class for you:
namespace YourSolution
{
using System;
using System.Collections.Generic;
public partial class News
{
public int ID { get; set; }
public string Title { get; set; }
public int UserID { get; set; }
public virtual UserProfile User{ get; set; }
}
}
and you want do some work arounds to preserve your you data annotations and attributes. So, follow these steps:
First, add two classes some where (wherever you want, but it's better to be in Models) like the following:
namespace YourSolution
{
[MetadataType(typeof(NewsAttribs))]
public partial class News
{
// leave it empty.
}
public class NewsAttribs
{
// Your attribs will come here.
}
}
then add what properties and attributes you want to the second class - NewsAttribs here. :
public class NewsAttrib
{
[Display(Name = "News title")]
[Required(ErrorMessage = "Please enter the news title.")]
public string Title { get; set; }
// and other properties you want...
}
Notes:
1) The namespace of the generated entity class and your classes must be the same - here YourSolution.
2) your first class must be partial and its name must be the same as EF generated class.
Go through this and your attribs never been lost again ...

Code first Type per hierarchy

I use EF 5 with the code first approach. Now I try to define a "code" table in which I want to have several different codes (like address code, medium code, etc.). In this table I just have the following properties: ID (Guid), Name (String), Description (String) and a discriminator (in this case something like the type of the code: address code, medium code, etc.).
So I defined the following base class:
public abstract class Code : EntityBase
{
public string Name { get; set; }
public string Beschreibung { get; set; }
}
Then I derived two classes from code
public class AddressCode : Code {}
public class MediumCode : Code {}
The class EntityBase is abstract and just defines the Id property, we use it for every POCO class...
The goal is that I can use AddressCode as a property on my address POCO class:
public class Adresse : EntityBase
{
#region Properties
public string Name1 { get; set; }
public virtual AddressCode AddressCode { get; set; }
#endregion
}
The question now is, how can I explain EF how to do that? Anyone can help?
Thanks
Marco
Thanks for your answer!
I tried to do it like you said. Unfortunately I get an error because of my EntityBase class:
public abstract class EntityBase
{
#region Properties
public virtual Guid Id { get; set; }
public virtual bool IsValid
{
get
{
{
return Validate();
}
}
}
[NotMappedAttribute]
public virtual IList<ValidationFailure> ValidationFailures { get; set; }
#endregion
#region Methods
private bool Validate()
{
var validatorFactory = new AttributedValidatorFactory();
IValidator validator = validatorFactory.GetValidator(GetType());
if (validator == null)
{
return true;
}
ValidationResult validationResult = validator.Validate(this);
ValidationFailures = validationResult.Errors;
return validationResult.IsValid;
}
#endregion
}
The error message is:
You cannot use Ignore method on the property 'ValidationFailures' on type 'Entities.AdresseCode' because this type inherits from the type 'Entities.EntityBase' where this property is mapped. To exclude this property from your model, use NotMappedAttribute or Ignore method on the base type.
As you can see I already defined the property ValidationFailures as NotMapped but still I get this error.. Do you have an idea?
Thanks
Marco
Just create a context (derived from DbContext)
public class AddressesDb : DbContext
{
public DbSet<Code> Codes { get; set; }
public DbSet<Adresse> Adressen { get; set; }
}
And (when used in code) EF will create a database with default table and column names. It will create a discriminator column of type text (nvarchar) which will contain the names of the classes that derive from Code.
If you want different names and/or types you should either use data annotations or fluent API to configure these.
Finally I got it work!
In the DBContext be aware to define DbSets for the code derived classes before all the other POCO's and then it works!

DataAnnotations MetadataType Class Ignores Base Class Properties

I've run into a bit of a wall in trying to use the .NET DataAnnotations feature to provide simple validations in a derived class. I am marking up my class with the standard annotations included in .NET 4 (from the System.ComponentModel.DataAnnotations namespace), then using the MS Enterprise Library v5 Validation Block to process the rules.
I have a number of objects derived from a common base class, which contains properties common to all of my objects. For validation purposes, I may have different rules for the various classes derived from this class.
Here's a simplified example:
public abstract class PersonBase
{
public int Id { get; set; }
public string Name { get; set; }
}
[MetadataType(typeof(CustomerMD))]
public class Customer : PersonBase
{
}
[MetadataType(typeof(ManagerMD))]
public class Manager : PersonBase
{
}
public class CustomerMD
{
[Required]
[StringLength(20, ErrorMessage="Customer names may not be longer than 20 characters.")]
public object Name { get; set; }
}
public class ManagerMD
{
[Required]
[StringLength(30, ErrorMessage = "Manager names may not be longer than 30 characters.")]
public object Name { get; set; }
}
// calling code
var invalidCustomer = new Customer {Id=1, Name=string.Empty};
var valFactory = EnterpriseLibraryContainer.Current.GetInstance<ValidatorFactory>();
var customerValidator = valFactory.CreateValidator<Customer>();
var validationResults = customerValidator.Validate(invalidCustomer);
// validationResults.IsValid should equal False, but actually equals True.
I have found that I can get the expected validation results if I push the annotations down to the base class, but then I lose the ability to fulfill different requirements for different types. Also, if I put class-specific properties on a derived class and provide metadata for these properties, I get results, but only for these properties, not the properties from the base class.
I haven't yet tried using the EntLib provided validation attributes; I'd prefer to keep the library this lives in free of dependencies from outside the core framework, if at all possible.
Am I missing something, or am I just out of luck here?
I think I have a workable solution for this.
It appears that the Metadata class will not provide validation of properties belonging to the superclass of the target object. In order to get Metadata to work with this, I needed to mark the superclass properties as virtual, then provide overrides for the properties that I wanted to validate.
Example (see question above for original example):
public abstract class PersonBase
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
[MetadataType(typeof(CustomerMD))]
partial class Customer : PersonBase
{
public override string Name
{
get
{
return base.Name;
}
set
{
base.Name = value;
}
}
}
With the override in place, the validator works as expected. It's a little more work, but it will get the job done.
I also tried adding annotations to the base class as fallback default rules; this allows me to have a base set of rules and override them as needed on a case by case basis. Looking good.
I run into the same issue and couldn't make it annotate a base class with Attributes using MethadataType. Like Scroll Lock I did the overriding part for base class virtual properties. On top of it I made "shadowing" for the none virtual properties.
public class BaseClass
{
public virtual int Id {get;set;}
public string Name {get;set;}
}
public class DerivedClass
{
[SomeAttribute]
public ovveride int Id {get{ return base.Id;} set{ base.Id = value;}}
[SomeAttribute]
public new string Name {get{ return base.Name;} set{ base.Name = value;}}
}