Does adding [NotMapped] to a partial class avoid mapping the entire class? - c#

I have set up my EF code-first database but want to add additional derived properties. (Yes, it should be in a view model, we can discuss another time why it is this way.) I have created a partial class extending the actual table class. If I add a [NotMapped] to the new partial, will it avoid mapping the additional properties I add there or will it apply to the entire class?

It will apply to the entire class. Remember that a partial class is simply a way of splitting a class into multiple files. From the official docs:
At compile time, attributes of partial-type definitions are merged.
So this:
[SomeAttribute]
partial class PartialEntity
{
public string Title { get; set; }
}
[AnotherAttribute]
partial class PartialEntity
{
public string Name { get; set; }
}
Is equivalent to writing:
[SomeAttribute]
[AnotherAttribute]
partial class PartialEntity
{
public string Title { get; set; }
public string Name { get; set; }
}
If you want to add a partial class without having the properties included in the model, you will need to add the NotMapped attribute to the individual items:
partial class PartialEntity
{
public string Title { get; set; }
}
partial class PartialEntity
{
[NotMapped]
public string Name { get; set; }
}

Related

Is there any way to disable the validation of inherited properties?

I have the following entities for example:
public class BaseClass
{
[Required]
public virtual string DisplayName { get; set; }
}
public class FirstChildClass: BaseClass
{
public int Id { get; set; }
}
public class SecondChildClas: BaseClass
{
public int Id { get; set; }
}
Then i have the following viewmodel:
public class MyViewModel
{
public FirstChildClass FirstProperty { get; set; }
public SecondChildClass SecondProperty { get; set; }
}
In my View i have a form which submits the following properties FirstChildClass.Id and SecondChildClass.Id.
My problem is that the inherited DisplayName is added to my ModelState due to the [Required] attribute. I'd like to ignore the validation of inherited properties without removing them explicitly from the ModelState with Remove().
Is there any way to accomplish it?
I would suggest not using inheritance here. What is BaseClass:
I have DisplayName and it should be Required but not always, it depends, looks in all derived classes to understand how I work.
If you really want to go that way check if you can make this property virtual, and add attribute only to one derived class.

Adding attributes to a derived type

I am working with entity-framework. I have a partial class called Company that is generated by EF. The partial class looks like:
The type 'BaseModels.Company' already contains a definition for 'CompanyName'"
public partial class Company {
public string CompanyId { get; set; }
public string CompanyName { get; set; }
}
What I want to do is create a derived class from Company that has an extra property.
public class MyCompany : Company {
public string UploadName { get; set; }
}
But I want to decorate the base type property CompanyName with a custom attribute.
I went to the following location:
How do I add an attribute to the field of the base class from child class?
Which does answer my question. The problem is if I marked the CompanyName property in the base class as "virtual", then EF could regenerate the code which would override my stuff.
I tried to define a partial class, but VS 2013 complained when I tried to add:
public partial class Company {
[Renderer("html")]
public virtual string CompanyName { get; set; }
}
by stating that the property name already existed.
How would I get around this hurdle?
You cannot with partial class define property that already exists. You add attribute over existing property you need to use MetadataTypeAttribute. Create partial class:
[MetadataType(typeof(CompanyMetadata))]
public partial class Company { }
and add metadata class to your project with your property with desired attribute:
public class CompanyMetadata
{
[Renderer("html")]
public string CompanyName { get; set; }
}
Make Company an abstract class. Then use override keyword with CompanyName to add the custom attribute. You can also add UploadName.

Entity Model + Scalar Property + Custom Type

When using entity framework's model designer is it possible to add a property to an entity that is not one of the standard types?
I have these two entities. The one, VirusDescription I would like to add another property which is a class I wrote however when you go to change the type of the property it only gives you basics... i.e. strings, int16...etc. Is there a way to include custom types in the designer?
I can go into the code that the designer generates and just add it myself and everything works fine but I would like the code and the designer to be consistent.
Here is the class definition for the VirusDescription entity which I updated by hand. If there is a way to update the designer from the corresponding code that would work too.
namespace Trojan.Database
{
using System;
using System.Collections.Generic;
public partial class VirusDescriptionItems
{
public string ItemId { get; set; }
public string VirusId { get; set; }
public bool On_Off { get; set; }
public System.DateTime DateCreated { get; set; }
public short AttributeId { get; set; }
public short CategoryId { get; set; }
public virtual Attribute Attribute { get; set; } //Added
public virtual Category Category { get; set; } //Added
}
}
You can create a complex type within the entity model browser and extend the generated class using partial implementations.

Data Annotations on Entity Partial Classes

I have refactored an application which uses EF5 Database First. The application uses metadata classes to add data annotations to the entity properties. Before the refactor, these worked. They are mostly just display names and data formats.
Example:
[MetadataType(typeof(QueryDetailsResultMetadata))]
public partial class QueryDetailsResult : IPortfolio
{
public string Source { get { return "Local"; } }
}
public class QueryDetailsResultMetadata
{
//Fields from QueryDetailsResult requiring annotations
[Display(Name = "Company Name")]
public string SiteName { get; set; }
[Display(Name = "Contact Telephone Number")]
public string ContactTelNo { get; set; }
}
Before the refactor, the partial class did not inherit from an interface and it did not have the non mapped property. These changes are however required. Neither of these two should be causing a problem as both are well documented as valid solutions.
The interface looks like this
public interface IPortfolio
{
int Id { get; set; }
string SiteName { get; set; }
string YearOfManufacture { get; set; }
string Contact { get; set; }
string ContactTelNo { get; set; }
string Source { get;}
}
The display uses the properties like this
#Html.DisplayNameFor(model => model.Portfolio.ContactTelNo)
On the View at runtime, the property names are shown rather than the display names. Any ideas why? I can't see any reason for the annotations to be broken
//edit
I tried moving the annotations on to the new non-mapped fields in the partial and removed them from the metadata class. To seee if it had any effect. None. Also double checked the edmx is in the same Namespace as the partial class and metadata file which it is.
Any thoughts on what to check or try? Not having much success this end, most google results are just saying to use a metadata class which is already in place.
//2nd Edit
Moving annotations out of metadata class and on to the interface did the trick.
It is a little bit confusing how the DataAnnotation attributes are wroking with interfaces because:
at one hand classes don't inherit attributes from their interfaces: Is it possible to use DataAnnotations with Interfaces?
the the other hand you can/need put the attributes on the interfaces: ASP.NET MVC DisplayAttribute and interfaces
But how it works only depends on the type of your "container" in the view so lets consider the following types:
public class QueryDetailsResult : IPortfolio
{
public string SiteName { get; set; }
}
public interface IPortfolio
{
string SiteName { get; set; }
}
So if you have #Html.DisplayNameFor(model => model.Portfolio.SiteName) in your view
and your model class looks like
public class Model {
public QueryDetailsResult Portfolio { get; set; }
}
then you need to put the DisplayAttribute on the SiteName property of your QueryDetailsResult class because MVC looks for the "container" type in the model.Portfolio.SiteName expression which is QueryDetailsResult
but if you have your model class defined as
public class Model {
public IPortfolio Portfolio { get; set; }
}
then you need to put it on the SiteName property of the IPortfolio interface because your "container" type is the IPortfolio interface.

Replacement for [Display] Attribute

Given the class:
public class Item
{
[Key]
public int ID { get; set; }
[Display]
public string Name { get; set; }
public string Observation { get; set; }
public DateTime? Done { get; set; }
}
I know i can define my [Key] Attribute and other mapping settings by create a mapping class in another project and inheriting from EntityTypeConfiguration.
but how can i replace the [display] attribute so i don't have to add a reference to System.ComponentModel.DataAnnotations to my common dll?
tell me if i'm not clear enough
You can create your own attribute, then write a class that inherits AssociatedMetadataProvider and reads data from your attribute into a ModelMetadata instance.
Your class would be similar or identical to the built-in version.

Categories

Resources