DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Building Scalable Real-Time Apps with AstraDB and Vaadin
Register Now

Trending

  • Design Patterns for Microservices: Ambassador, Anti-Corruption Layer, and Backends for Frontends
  • Never Use Credentials in a CI/CD Pipeline Again
  • What Is mTLS? How To Implement It With Istio
  • Redefining DevOps: The Transformative Power of Containerization

Trending

  • Design Patterns for Microservices: Ambassador, Anti-Corruption Layer, and Backends for Frontends
  • Never Use Credentials in a CI/CD Pipeline Again
  • What Is mTLS? How To Implement It With Istio
  • Redefining DevOps: The Transformative Power of Containerization
  1. DZone
  2. Data Engineering
  3. Data
  4. Entity Validation and the Entity Framework – Part 1

Entity Validation and the Entity Framework – Part 1

Rob Sanders user avatar by
Rob Sanders
·
Oct. 12, 13 · Interview
Like (0)
Save
Tweet
Share
3.83K Views

Join the DZone community and get the full member experience.

Join For Free

Introduction

The next logical step in my journey across the Entity Framework v6 RC1 after having established a fairly robust data access approach was to imbue my solution with some more “smarts” when it came to entity validation.

Out-of-the-box Entity Framework POCO entities are exactly as advertised – plain old CLR objects – and, as such, do not contain any inherent validation hints or help.

There are a plethora of validation approaches available, including extending the entity classes with partial classes, but I wanted something implemented which would be core to the data access approach – and (because I’m lazy) something that didn’t require any hand written code, outside of modifying a template.  After all, the EDMX already knows about nullable fields and field lengths, right?  Why not take advantage of that knowledge?

To be clear – this is not an approach designed to validate entities in an interactive fashion as there are other approaches which would work better, including UI validation.  Instead, this is an implementation designed to catch (and reject) any inserts or updates which would genuinely fail if an attempt to commit the changes was made – i.e. this is a last ditch sanity check.

Interrogating the T4 template

To accomplish what I want to do, you’ll have to be comfortable hand editing the T4 template which is used to generate the Entity Framework POCO entities.  If you haven’t done a lot of templating before, this might seem a bit daunting at first.

Untitled_thumb[2]

If you expand the <DataModel>.edmx file, you’ll see there are a host of linked dependency files.  The one we’re interested in specifically is called Model.tt and it is a direct dependency of the EDMX file itself.

There’s a fairly obvious format to the template, and you can actually play with the template and see the results.  Every time you save the template it triggers the templating engine – but be warned, any errors will break the template and you’ll get an error message.

An Example Schema Object

Let’s look at an example from my previous data schema.  As you can see, nothing terribly scary here, but there are a couple of required fields (not-nullable) and some fields which have defined lengths (we’re focusing on strings here).

image_thumb5

What I’m aiming to produce are some Data Annotations decorating the appropriate properties on my corresponding Catalog data entity, which would look like this (apologies for the text wrapping):

// Simple Properties

[Required(ErrorMessage="[Property 'CatalogId' in entity 'Catalog' is a required property.]")]
public int CatalogId { get; set; }
        
[StringLength(100, ErrorMessage="[The field 'Title' in entity 'Catalog' cannot be longer than 100 characters.]")]
[Required(ErrorMessage="[Property 'Title' in entity 'Catalog' is a required property.]")]
public string Title { get; set; }
        
[StringLength(400, ErrorMessage="[The field 'Description' in entity 'Catalog' cannot be longer than 400 characters.]")]
public string Description { get; set; }

public Nullable<System.DateTime> DateTaken { get; set; }
        
[StringLength(50, ErrorMessage="[The field 'OriginalFilename' in entity 'Catalog' cannot be longer than 50 characters.]")]
public string OriginalFilename { get; set; }

public Nullable<int> Orientation { get; set; }

// End Simple Properties

To accomplish this I also need the class implementation to use the following namespace:

using System.ComponentModel.DataAnnotations;

Modifying the T4 Template

There are two key changes which need to be made.  The first is to insert the namespace – which I’ve done in a less than graceful manner by just dropping it into the template right after the BeginNamespace call:

foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>
(itemCollection))
{
    fileManager.StartNewFile(entity.Name + ".cs");
    BeginNamespace(code);
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
using System.ComponentModel.DataAnnotations;

<#=codeStringGenerator.EntityClassOpening(entity)#> : EntityBase
{

Two things to note here – in bold – one is the base class I added previously, and the second is the DataAnnotations namespace.  Next, we’ll add the logic to prefix properties with the annotations we desire for validation.

You’re looking to move beyond the default constructor and find a section which looks like this:

foreach (var edmProperty in simpleProperties)
{

This section handles generation of (simple) properties for the entity.  There are two main conditions we want to check for – non-nullable properties (required fields) and fields with a fixed length.  Here is the full (modified) code for the section of the T4 template which generates simple properties:

Note: I started writing this by hand until found this problem  solved in the following article, but I modified the annotations to provide a bit more context (including the property names and source entity type).  What you see here is more or less copied from the linked article.

var simpleProperties = typeMapper.GetSimpleProperties(entity);
if (simpleProperties.Any())
{
foreach (var edmProperty in simpleProperties)
{
// begin max length attribute
if (code.Escape(edmProperty.TypeUsage) == "string")
{
int maxLength = 0;
if (edmProperty.TypeUsage.Facets["MaxLength"].Value != null && 
    Int32.TryParse(edmProperty.TypeUsage.Facets["MaxLength"].Value.ToString(), out maxLength))
{
#>    
    [StringLength(<#=code.CreateLiteral(maxLength)#>, 
    ErrorMessage="[The field '<#=edmProperty.Name#>' in entity '<#=entity.Name#>' cannot be longer than <#=code.CreateLiteral(maxLength)#> characters.]")]
<#
}
}
    // begin required attribute
  if (edmProperty.TypeUsage.Facets["Nullable"].Value.ToString() =="False")
  {
#>
    [Required(ErrorMessage="[Property '<#=edmProperty.Name#>' in entity '<#=entity.Name#>' is a required property.]")]
<#
    }
#>    <#=codeStringGenerator.Property(edmProperty)#>
<#
        }
    }
#>

Again, apologies for the wrapped and poorly indented code – limitations of this blogging format unfortunately.  I’ve included my copy of my model.tt below so you can get a properly formatted version.  Code in italics is original non-modified template code.

The Outcome

This produces the following generated entity – with data annotations:

// Simple Properties
[Required(ErrorMessage="[Property 'CatalogId' in entity 'Catalog' is a required property.]")]
public int CatalogId { get; set; }
        
[StringLength(100, ErrorMessage="[The field 'Title' in entity 'Catalog' cannot be longer than 100 characters.]")]
[Required(ErrorMessage="[Property 'Title' in entity 'Catalog' is a required property.]")]
public string Title { get; set; }
        
[StringLength(400, ErrorMessage="[The field 'Description' in entity 'Catalog' cannot be longer than 400 characters.]")]
public string Description { get; set; }
public Nullable<System.DateTime> DateTaken { get; set; }
        
[StringLength(50, ErrorMessage="[The field 'OriginalFilename' in entity 'Catalog' cannot be longer than 50 characters.]")]
public string OriginalFilename { get; set; }
public Nullable<int> Orientation { get; set; }
// End Simple Properties

Summary

We’re not done just yet.. but this is a start.  In part 2, I’ll be showing how this effort is put to use, by integrating it into my previously documented data access approach.  Next article should be up soon.

My Template

Here’s my [ T4 Template ]

Massively Helpful

  •  http://blogs.msdn.com/b/lgmorand/archive/2010/12/31/entity-framework-template-t4-and-data-annotations.aspx
  •  http://msdn.microsoft.com/en-us/library/system.data.metadata.edm.edmproperty.aspx
Entity Framework Template Data access

Published at DZone with permission of Rob Sanders, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Design Patterns for Microservices: Ambassador, Anti-Corruption Layer, and Backends for Frontends
  • Never Use Credentials in a CI/CD Pipeline Again
  • What Is mTLS? How To Implement It With Istio
  • Redefining DevOps: The Transformative Power of Containerization

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: