EF Designer from database with DataAnnotations - c#

Is there any way possible to generate the database object in model.edmx with DataAnnotations(like Required, StringLength)?

When you use database first approach with EF all your classes are generated as partial classes. Which means you can spilt the definition over two or more source files. If you make changes to the generate class it will be overwritten.
Let's say you have a partial class of User generated by EF as
public partial class User
{
public string Username { get; set; }
public string Telphone { get; set; }
}
Now to use DataAnnotations on the properties of User you would create a new source file with the same name in the same namespace and make use of MetadataType attribute as:
[MetadataType(typeof(UserMetaData))]
public partial class User
{
public string Username { get; set; }
public string Telphone { get; set; }
}
public class UserMetaData
{
[Required]
[Display(Name = "User name")]
public string Username { get; set; }
[DataType(DataType.PhoneNumber)]
[Display(Name = "Telephone number")]
public string Telephone { get; set; }
}
As you can see I've used MetadataType attribute in the second example which specifies the metadata class to associate with a data model class.

Related

Multiple metadata classes for entity

Suppose I have 2 entities one is UserMaster another is ProjectMaster, now there are few common properties in both the entities and I need to apply same data annotations and attributes on both set of common properties which I do using metadata classes, now my question is there any way that I have a common metadata class for all this common properties across entities,so that I don't need apply data annotation and attributes for common properties again and again and if yes then how to achieve this.
You can create a base metadata class and the other metadata class derive from the base and add some other properties.
Example:
In the below example I supposed you can't derive Class2 from Class1 so I have inheritance only between metadata classes, otherwise you can simply have inheritance between your model classes.
[MetadataType(typeof(Class1Metadata))]
public class Class1
{
public string Id { get; set; }
public string Name { get; set; }
}
[MetadataType(typeof(Class2Metadata))]
public class Class2
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class Class1Metadata
{
[Display(Name="Id1")]
public string Id { get; set; }
[Display(Name = "Name1")]
public string Name { get; set; }
}
public class Class2Metadata:Class1Metadata
{
[Display(Name = "Description2")]
public string Description { get; set; }
}

Are Metadata classes same as ViewModel in asp.net MVC?

I'm a little confused about this one. I read about metadata classes in this article on MSDN.
It says that the reason for creating metadata is not to mess with the auto generated models by EF.
So this is a model generated by EF:
namespace Blog.Models
{
using System;
using System.Collections.Generic;
public partial class Article
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Article()
{
this.ArticleTags = new HashSet<ArticleTag>();
this.Comments = new HashSet<Comment>();
}
public int ArticleID { get; set; }
public string PostTitle { get; set; }
public string PostContent { get; set; }
public string PostLinkText { get; set; }
public Nullable<System.DateTime> PostDateTime { get; set; }
public Nullable<int> PostAuthorID { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ArticleTag> ArticleTags { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Comment> Comments { get; set; }
public virtual Admin Admin { get; set; }
}
}
and this is metadata class for Article model:
public class ArticleMetadata
{
[Display(Name = "Post Title")]
public string PostTitle { get; set; }
[Display(Name = "Content")]
public string PostContent { get; set; }
[Display(Name = "Link Text")]
public string PostLinkText { get; set; }
[Display(Name = "Post Date and Time")]
public DateTime? PostDateTime { get; set; }
[Display(Name = "Post Author")]
public int? PostAuthorID { get; set; }
}
linked to model class using PartialClasses.cs:
[MetadataType(typeof(ArticleMetadata))]
public partial class Article
{
}
Is the metadata class the same as a ViewModel??
If so, how are these different and which one should be used in my case?
class ArticleMetadata is a helper class for class Article, needed because you can't otherwise add those Annotation attributes to specific properties.
Together they form the Model part of MVC.
Note that the partial class can't help with the properties because it can't redefine them. It is used here only to link up the MetaData class.
For very simple operations (CRUD pages) you can use the Model directly. In all other case, create a ViewModel for each View. The Article Model will probably be used by an EditArticleViewModel.
In general you should create ViewModels to support Views, not one for each Model. One ViewModel could be composed of data from several Model classes.
No, they aren't the same.
Metadata classes allow you to define/add restraints to your class members.
View models are usually used to make it easier to use your model in a view. Such as having lists of SelectListItems for dropdowns, having properties to accept form post values, etc.
The two are usually used in conjunction, you add validation in your metadata class, and enforce it through the view model.
In your specific case, it seems all you need is a metadata class.

How to use AutoMapper with Entity Framework Database First approach

I am working on MVC 5, Entity Framework with Db First Approach. Whenever i use
public class Customer
{
[Required]
public virtual string CustomerID { get; set; }
[Required]
[StringLength(15)]
public virtual string CompanyName { get; set; }
public virtual string Address { get; set; }
public virtual string City { get; set; }
public virtual string PostalCode { get; set; }
[Country(AllowCountry="USA")]
public virtual string Country { get; set; }
[Phone]
public virtual string Phone { get; set; }
}
for Validation in Entity Framework generated class and if i update my .edmx file i lost all code that i was written. Someone suggest me use Auto-mapper. I try to find some basic example but i didn't get. Guide me. How to start and where from? I am new in MVC, Entity Framework.
There is another approach to retain the validation attribute code even if you update the model.
In the Models folder, add a class named Metadata.cs (class that contain all of the validation attributes).
using System;
using System.ComponentModel.DataAnnotations;
namespace YourProjectName.Models
{
public class CustomerMetadata
{
[Required]
public virtual int CustomerId { get; set; }
[Required]
[StringLength(15)]
public virtual string CompanyName { get; set; }
}
}
Next, you must associate the model classes with the metadata classes.For that In the Models folder, add a class named PartialClasses.cs.
using System;
using System.ComponentModel.DataAnnotations;
namespace YourProjectName.Models
{
[MetadataType(typeof(CustomerMetadata))]
public partial class Customer
{
}
}
Source

Cast IEnumerable<Inherited> To IEnumerable<Base>

I'm trying to cast an IEnumerable of an inherited type to IEnumerable of base class.
Have tried following:
var test = resultFromDb.Cast<BookedResource>();
return test.ToList();
But getting error:
You cannot convert these types. Linq to Entities only supports conversion primitive EDM-types.
The classes involved look like this:
public partial class HistoryBookedResource : BookedResource
{
}
public partial class HistoryBookedResource
{
public int ResourceId { get; set; }
public string DateFrom { get; set; }
public string TimeFrom { get; set; }
public string TimeTo { get; set; }
}
public partial class BookedResource
{
public int ResourceId { get; set; }
public string DateFrom { get; set; }
public string TimeFrom { get; set; }
public string TimeTo { get; set; }
}
[MetadataType(typeof(BookedResourceMetaData))]
public partial class BookedResource
{
}
public class BookedResourceMetaData
{
[Required(ErrorMessage = "Resource id is Required")]
[Range(0, int.MaxValue, ErrorMessage = "Resource id is must be an number")]
public object ResourceId { get; set; }
[Required(ErrorMessage = "Date is Required")]
public object DateFrom { get; set; }
[Required(ErrorMessage = "Time From is Required")]
public object TimeFrom { get; set; }
[Required(ErrorMessage = "Time to is Required")]
public object TimeTo { get; set; }
}
The problem I'm trying to solve is to get records from table HistoryBookedResource and have the result in an IEnumerable<BookedResource> using Entity Framework and LINQ.
UPDATE:
When using the following the cast seams to work but when trying to loop with a foreach the data is lost.
resultFromDb.ToList() as IEnumerable<BookedResource>;
UPDATE 2:
Im using entity frameworks generated model, model (edmx) is created from database, edmx include classes that reprecent the database tables.
In database i have a history table for old BookedResource and it can happen that the user want to look at these and to get the old data from the database entity framework uses classes with the same name as the tables to receive data from db. So i receive the data from table HistoryBookedResource in HistoryBookedResource class.
Because entity framework generate the partial classes with the properties i dont know if i can make them virtual and override.
Any suggestions will be greatly appreciated.
Typically you use AsEnumerable<T> in such cases:
var test = resultFromDb.AsEnumerable().Cast<BookedResource>();
This has the advantage of not enumerating the whole result at once (you don't loose the laziness).
try with:
resultFromDb.AsEnumerable().Cast<BookedResource>();

Extending LINQ to SQL generated classes

I have picked LINQ to SQL as ORM framework for ASP .NET MVC3 project. Everything was good before I was faced with need to put additional field 'Confirm Password' to registration form. As it was mentioned in one question on SO (unfortunately I can't find it at the moment), it's better to use interface to extend generated LINQ to SQL classes with validation attributes, instead of having another class for storing validation attributes. So here we go:
public interface IRegTry
{
[Required]
[Email]
string EMail { get; set; }
[Required]
[StringLength(100, ErrorMessage = "Should not exceed 100 symbols")]
string FirstName { get; set; }
[Required]
string Password { get; set; }
}
[MetadataType(typeof(IRegTry))]
public partial class RegTry : IRegTry { }
RegTry class is generated class by LINQ to SQL based on database entity.
On the View we have confirm password field, which should make sure that two typed password equals to each other.
So here we adding it:
public class RegTryViewModel : RegTry
{
[Required]
[EqualTo("Password", ErrorMessage = "You should type two identical passwords to continue")]
public string ConfirmPassword { get; set; }
}
View is strongly typed view with RegTryViewModel model.
I just ask here to make sure I'm doing everything right. The thing that makes me feel uncomfortable is that I spread validation logic between IRegTry interface and the RegTryViewModel class. But I can't add ConfirmPassword property to IRegTry interface because base SQL to LINQ class doesn't has it at all.
Thanks in advance guys!
I know that you already accepted an answer for this but I think it may be better to set this up using partial classes. As long as you set up the partial class in the same namespace with the same name, everything will get set up automatically. Here is an example of how I set this up in one of my projects:
namespace OperationsMetrics
{
[MetadataType(typeof(ClientStatMD))]
public partial class client_wkly_stat : IValidatableObject
{
public class ClientStatMD
{
[Required(ErrorMessage = "Client selection is required")]
public virtual int client_id { get; set; }
[Required(ErrorMessage = "SLAs met is required")]
public virtual int wkly_sla_met { get; set; }
[Required(ErrorMessage = "Total SLAs possible is required")]
public virtual int wkly_sla_req { get; set; }
[Required(ErrorMessage = "Number of input files is received")]
public virtual int num_inp_files_rec { get; set; }
[Required]
public string client_name { get; set; }
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (wkly_sla_met > wkly_sla_req)
{
yield return new ValidationResult("SLAs met cannot be greater that SLAs possible");
}
}
public string client_name { get; set; } //this isn't a part of the actual db object but can still be accessed in the Validate method
}
}
You can set up the Partial Class as an IValidatableObject which implements its own Validate method. You can have a check for Confirm==Password in your Validate method.
You can get some more information in this Pluralsight Video
If you are using View Model classes, you don't need validation logic connected to your DAL Model classes, so you shouldn't need that validation interface linked to the DAL Model class.

Categories

Resources