Entity validaton using Custom Data Annotation attributes

Ok. Today I have extended the validation part a bit. The code is about 90% the same from the post I wrote yesterday (Entity framework 4 – Part 5 – Validation using Data Annotations). But I have now added some custom data annotation attributes and made it possible for the services to add custom validation of the entities.

I will not show all the code since much of it is covered in Entity framework 4 – Part 5 – Validation using Data Annotations and as always, you can download a complete code example.

The EntityValidator
It uses the builtin Validator and ValidationResult found in System.ComponentModel.DataAnnotations. It validates sent entities by looking at your entity for validation attributes. I have now also made it possible to inject a Func, which lets you perform custom validation. What I medan by this is that you can provide a func that generates validation results that gets merged into the validation results generated by the validation attributes. The Func takes the Entity and a bool as in-params. The bool contains true if the validation attributes resulted in a valid entity. The result of the Func should be an IEnumerable, which will be merged by the validationresults generated by the validation attributes.

public class EntityValidator<T> where T : IEntity
{
    public EntityValidationResult Validate(T entity, Func<T, bool, IEnumerable<ValidationResult>> customValidation = null)
    {
        var validationResults = new List<ValidationResult>();
        var vc = new ValidationContext(entity, null, null);
        var isValid = Validator.TryValidateObject(entity, vc, validationResults, true);

        if (customValidation != null)
            validationResults.AddRange(customValidation(entity, isValid));

        return new EntityValidationResult(validationResults);
    }
}

The Service
To ease things in my services I have implemented a helper method in a base-class which my services extends. This method will only invoke the customvalidation Func if the validation attributes haven’t generated an invalid entity.

public abstract class Service
{
    protected IEntityStore EntityStore { get; private set; }

    protected Service(IEntityStore entityStore)
    {
        EntityStore = entityStore;
    }

    protected EntityValidationResult ValidateEntity<T>(T entity, Func<T, IEnumerable<ValidationResult>> customValidation = null)
        where T : IEntity
    {
        Func<T, bool, IEnumerable<ValidationResult>> customValidationProxy = null;
        
        if (customValidation != null)
            customValidationProxy = (e, isValid) => isValid ? customValidation(e) : null;

        return new EntityValidator<T>().Validate(entity, customValidationProxy);
    }
}

In my Security-service I provide some custom validation to check if the Email isn’t allready taken, by providing a customvalidation Func. I also make use of some extension methods to get access to named queries for my UserAccount entities.

public class SecurityService : Service, ISecurityService
{
    public SecurityService(IEntityStore entityStore)
        : base(entityStore)
    {
    }

    public ServiceResponse<UserAccount> SetupNewUserAccount(UserAccount userAccount)
    {
        var validationResult = ValidateEntity<UserAccount>(userAccount, CustomValidationForSettingUpNewAccount);

        if (!validationResult.HasViolations)
        {
            EntityStore.AddEntity(userAccount);
            EntityStore.SaveChanges();
        }

        return new ServiceResponse<UserAccount>(userAccount, validationResult);
    }

    private IEnumerable<ValidationResult> CustomValidationForSettingUpNewAccount(UserAccount userAccount)
    {
        var violations = new List<ValidationResult>();

        var emailIsTaken = EntityStore.EmailIsTakenByOther(userAccount.Username, userAccount.Email);
        if (emailIsTaken)
            violations.Add(new ValidationResult("Email is allready taken."));

        return violations;
    }
}

Named queries – Extension methods to my Entitystore
Since I don’t use a custom implementaion of a Entitystore for the application (although there is one provided in the example code), I have implemented my specific entity queries as extension methods. So if I want access to e.g. specific queries for my useraccounts, I just import the namespace where they are located (Sds.Christmas.Storage.Queries.UserAccounts).

using Sds.Christmas.Storage.Queries.UserAccounts;

public static class UserAccountQueries
{
    public static bool EmailIsTakenByOther(this IEntityStore entityStore, string username, string email)
    {
        return
            entityStore.Query<UserAccount>().Where(
                u =>
                    u.Username.Equals(username, StringComparison.InvariantCultureIgnoreCase) &&
                    u.Email.Equals(email, StringComparison.InvariantCultureIgnoreCase)).Count() > 0;
    }
}

Custom data annotaions
Since my UserAccount contains an Email I have created a custom Email-validationattribute and applied it to the Email-property. The errormessages are retrieved via resx-files.

[Serializable]
public class UserAccount
    : Entity
{
    [Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserAccountRequiredUsername", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    [StringRange(MinLength=5, MaxLength=20, ErrorMessageResourceName = "UserAccountInvalidLength", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    public virtual string Username { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserAccountRequiredPassword", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    public virtual string Password { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserAccountRequiredEmail", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    [Email(ErrorMessageResourceName = "UserAccountEmailHasInvalidFormat", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    public virtual string Email { get; set; }
}

[Serializable]
public class EmailAttribute : RegexAttribute
{
    public EmailAttribute() : base(@"^[\w-\.]{1,}\@([\w]{1,}\.){1,}[a-z]{2,4}$", RegexOptions.IgnoreCase)
    {}
}

[Serializable]
public class RegexAttribute : ValidationAttribute
{
    public string Pattern { get; set; }
    public RegexOptions Options { get; set; }

    public RegexAttribute(string pattern, RegexOptions options = RegexOptions.None)
    {
        Pattern = pattern;
        Options = options;
    }

    public override bool IsValid(object value)
    {
        return IsValid(value as string);
    }

    public bool IsValid(string value)
    {
        return string.IsNullOrEmpty(value) ? true : new Regex(Pattern, Options).IsMatch(value);
    }
}

If you now try to add two different useraccounts with the same Email, you will not succed.

//Setup new useraccount using Service
var userAccount = SetupNewUserAccount();
var userAccount2 = SetupNewUserAccount(); //=> Gives Email is allready taken error.

That’s it. Don’t forget to download and explore the code.

//Daniel

Entity framework 4 – Part 5 – Validation using Data Annotations

This post is part of a series of post where I cover different aspects of the new version of Entity framework and the CTP features. I do focus on creating a POCO solutions, hence I don’t use the designer to generate my model.

Part 1 – Getting started
Part 2 – Relationships between non public members
Part 3 – Adding pluralization support to a non strongly typed ObjectContext.
Part 4 – Autoregister Entitymappings

Download the code.

This time I will look at validation using the “System.ComponentModel.DataAnnotations” lib. NOTE! That it doesn’t say “System.Data.Entity.DataAnnotations” or any other specific part of the .Net framework. It is a common lib that could be used in e.g ASP.Net MVC.

Specify the rules
Lets start with the rules. I have chosen to decorate my entities with attributes to specify the rules for them. This is as easy as:

1. Add reference to “System.ComponentModel.DataAnnotations”
2. Import namespace
3. Start decorating your classes.

This looks like:

[Serializable]
public class UserAccount
    : Entity
{
    [Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserAccountRequiredUsername", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    public virtual string Username { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserAccountRequiredPassword", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    public virtual string Password { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserAccountRequiredEmail", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    public virtual string Email { get; set; }
}

I have not created any custom attribute to take care of specific validation like an “EmailAttribute”, but it can be done. I have chosen to go with resources, but you can go with simple errormessages which would look like:

[Required(AllowEmptyStrings = false, ErrorMessage="You must provide an username.")]
public virtual string Username { get; set; }

Validate an entity
In this example I’m performing the validation in my services. This is something that isn’t necessary. E.g if you are using the new MVC 2 the default modelbinder can handle the validation for you.

To fulfill “DRY” (Dont repeat yourself) I have created a base class for my services, which contains a helper-method that validates entities. The method is “ValidateEntity”. It returns an instance of my EntityValidationResult-class which contains the violations. I’m using this instance to determine if the entity should be persisted or not. The violations are passed back to the serviceconsumer via a ServiceResponse, so I don’t throw any ugly business exceptions.

public class SecurityService : Service, ISecurityService
{
    public SecurityService(IEntityStore entityStore)
        : base(entityStore)
    {
    }

    public ServiceResponse<UserAccount> SetupNewUserAccount(UserAccount userAccount)
    {
        var validationResult = ValidateEntity<UserAccount>(userAccount);

        if (!validationResult.HasViolations)
        {
            EntityStore.AddEntity(userAccount);
            EntityStore.SaveChanges();
        }

        return new ServiceResponse<UserAccount>(userAccount, validationResult);
    }
}

The ValidateEntity method is really simple, since it just consumes another object, my EntityValidator. The code for this looks like:

In the baseclass: “Service”:

protected EntityValidationResult ValidateEntity<T>(T entity)
    where T : IEntity
{
    return new EntityValidator<T>().Validate(entity);
}
public class EntityValidator<T> where T : IEntity
{
    public EntityValidationResult Validate(T entity)
    {
        var validationResults = new List<ValidationResult>();
        var vc = new ValidationContext(entity, null, null);
        var isValid = Validator.TryValidateObject(entity, vc, validationResults);

        return new EntityValidationResult(validationResults);
    }
}

The EntityValidator just consumes classes found in the System.ComponentModel.DataAnnotations library and returns eventual violations by wrapping them in my EntityValidationResult-class.

[Serializable]
public class EntityValidationResult
{
    public IList<ValidationResult> Violations { get; private set; }
    public bool HasViolations
    {
        get { return Violations.Count > 0; }
    }

    public EntityValidationResult(IList<ValidationResult> violations = null)
    {
        Violations = violations ?? new List<ValidationResult>();
    }
}

Handle the violations
Since I’m just fiddling a bit I have a simple consoleapplication which only outputs the errors:

private static void IfFailedServiceOperationInformUser<T>(ServiceResponse<T> serviceResponse)
{
    if (serviceResponse.Status == ServiceResponseStatuses.Succeeded)
        return;

    Console.WriteLine("Service failed!");

    if (serviceResponse.ValidationResult.HasViolations)
    {
        Console.WriteLine("Violations are:");
        foreach (var violation in serviceResponse.ValidationResult.Violations)
        {
            foreach (var member in violation.MemberNames)
                Console.WriteLine("\t+" + member);

            Console.WriteLine("\t" + violation.ErrorMessage);
        }
    }
}

Thats it for now. As always you can download a complete example, which has evolved since part 1 of this post-series.

//Daniel

Entity framework 4 – Part 4 – Autoregister Entitymappings

This post is part of a serie of posts where I have been fiddeling a bit with Entity framework 4 Beta 2 and extension CTP2. The example code has evolved during the writing of this series and the goal has been to create infrastructure for persisting my entities without the need of Entity framework designers, attributes etc.

Part 1 – Getting started
Part 2 – Relationships between non public members
Part 3 – Adding pluralization support to a non strongly typed ObjectContext.

Download the code.

For this post I have made the EfEntityStore-class non-abstract, so that you can consume it directly. I have also implemented a method that Auto-registers your EntityMapping-classes. So to get entities stored in your database you need to:

1. Define a connection string
2. Create your entity classes
3. Create classes that defines the mapping for your entities
4. Create an instance of the EfEntityStore and register your mappings and you’r done.
5. Consume it.

Step 1 – Define connectionstring
Note! You don’t need to create the database. The entitystore will do this for you when you call:
EnsureCleanDatabaseExists or EnsureDatabaseExists.

<connectionStrings>
  <add name="Test" connectionString="Data Source=.\sqlexpress;Initial Catalog=Christmas;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/>
</connectionStrings>

Step 2 – Create entities
I have choosen to have a baseclass for all my entities.

[Serializable]
public abstract class Entity : IEntity
{
    public virtual int Id { get; set; }
}

[Serializable]
public class UserAccount
    : Entity
{
    public virtual string Username { get; set; }
    public virtual string Password { get; set; }
    public virtual string Email { get; set; }
}

Step 3 – Create entitymapping classes
For ease the autoregistration in Step 4 I have choosen to create a “dummy interface” that I implement in all my mapping classes, but it isn’t necessary if you don’t will use the generic autoregistration of your mappings.

public interface IChristmasEntityMapping
{
}

[Serializable]
public class UserAccountMapping : EntityConfiguration<UserAccount>, IChristmasEntityMapping
{
    public UserAccountMapping()
    {
        HasKey(u => u.Id);
        Property(u => u.Id).IsIdentity();

        Property(u => u.Email)
            .IsRequired()
            .IsNotUnicode()
            .MaxLength = 150;

        Property(u => u.Username)
            .IsRequired()
            .IsUnicode()
            .MaxLength = 20;

        Property(u => u.Password)
            .IsRequired()
            .IsUnicode()
            .MaxLength = 20;
    }
}

Step 4 & 5
Create an EntityStore instance and register the mappings. Then your done and you can start consuming it.

using(var es = new EfEntityStore("Test")) //Test is the name of the connection string
{
	es.MapEntities<IChristmasEntityMapping>();
	
	es.EnsureCleanDatabaseExists(); //Creates a new database.

	var userAccount =
		new UserAccount
			{
				Username = "littleben",
				Password = "ilovesnow",
				Email = "ben@thelittles.com"
			};

	es.SaveChanges();
}

In the donwloadable code I have implemented more entities and shown how StructureMap can help you with setting up the entitystore and a service.

Download the code and have fun with it.

The code below is not necessary, it only shows how you would use StructureMap to create an Entitystore and a service that consumers it.

public static class IoCContainer
{
	private static readonly Container _container;

	static IoCContainer()
	{
		_container = new Container();

		RegisterEntityStore();
		RegisterServices();

		//Debug.WriteLine(_container.WhatDoIHave());
	}

	private static void RegisterEntityStore()
	{
		_container.Configure(x => x
			.ForRequestedType<IEntityStore>()
			.CacheBy(InstanceScope.Singleton)
			.TheDefault.Is.OfConcreteType<EfEntityStore>()
			.WithCtorArg("connectionStringName").EqualTo("Test")
			.OnCreation(store => store.MapEntities<IChristmasEntityMapping>()));
	}

	private static void RegisterServices()
	{
		_container.Configure(x => x
			.ForRequestedType<ISecurityService>()
			.TheDefault.Is.OfConcreteType<SecurityService>()); //No need to specify cTor args since it will AutoMap IEntityStore from above
	}

	public static T Resolve<T>()
	{
		return _container.GetInstance<T>();
	}
}

//Daniel

Entity framework 4 – Part 3 – Adding pluralization support to a non strongly typed ObjectContext.

Part 1 – Getting started
Part 2 – Relationships between non public members

This is a post that continues on my previous post about how you could be building a ObjectContext in Entity Framework 4, without having them to be strongly typed. There’s no EDMX model etc. in your solutions.

This time I’m just going to show you have you can consume the PluralizationService to automatically get pluralized strings. I’m using it to get pluralized tablenames from my Entity framework-based, Entity store.

Download a complete example here. Ensure to update the config-file.

To pluralize the tables I need to consume the PluralizationService from Microsoft. This is really easy. Just call the factorymethod “CreateService” and provide for which culture you wan’t it to handle strings for and then let it pluralize a string.

var pluralizer = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en"));

string pluralized = pluralizer.Pluralize("UserAccount"); //Results in the string "UserAccounts"

Pluralize tablenames
This is done in my RegisterEntity method in my custom ObjectContextBuilder. The RegisterEntity method is there to let you register EntitySets in the ContextBuilder as well as register mapping information for entities; so that when the builder creates an ObjectContext, this information is passed along to the context.

/// <summary>
/// Registers the entity by setting up a set and configurations for it.
/// If no configuration is passed, only a Set will be registrered.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="entityConfiguration">The entity configuration.</param>
public void RegisterEntity<TEntity>(EntityConfiguration<TEntity> entityConfiguration = null)
    where TEntity : class, IEntity
{
    var pluralizedSetName = _pluralizer.Pluralize(typeof (TEntity).Name);

    RegisterSet<TEntity>(pluralizedSetName);
    if (entityConfiguration != null)
        Configurations.Add(entityConfiguration);
}

Above you can see that we are consuming the PluralizationService instance that has been created in the constructor. The SetName matches the name of the Entity but it is now is pluralized which leads to that the tables that are generated in the database, will have names that are pluralized.

The PluralizationService is for now found in System.Data.Entity.Design.

Download a complete example here. Ensure to update the config-file.

//Daniel

Entity framework 4 – Part 2 – Relationships between non-public members

Part 1 – Getting started
Part 3 – Adding pluralization support

Ok, the mission of this post is to extend the code from the previous post (about dynamic and non strongly typed object-contexts) and add some relations between the entities. I will show you one way how you could setup relationships between entities where members are not public.

Download a complete running example.

The example now is as follows:
A Person is represented by an user-account which can have many whishlists and each list can have many wishes.

The client code – Using Entity store
Lets look at the code that consumes the Entity store and creates some wishes for “Little Ben”.

//Create the User: Little Ben
var userAccount =
    new UserAccount
    {
        Username =    "littleben",
        Password =    "ilovesnow",
        Email =    "ben@thelittles.com"
    };

//Create Little Ben's Wishlist for Christmas
var wishlist = new WishList { WishedBy = userAccount };
wishlist.WishSomething(new Wish { Description = "A new computer." });
wishlist.WishSomething(new Wish { Description = "A new lens." });

using (IEntityStore es = new EfChristmasEntityStore("Test"))
{
    es.EnsureCleanDatabaseExists();

    //Store the useraccount, the wishlist and it's wishes.
    //No need for: es.AddEntity(userAccount); or es.AddEntity(wish1)...(wish2);
    es.AddEntity(wishlist);

    es.SaveChanges();
}

To make the above work, you need to tell the ContextBuilder how to map entities. This is done using a fluent API which is refactoring friendly, no bloated Xml is required.

UserAccount – mappings
Lets look at the mappings for the UserAccount.

[Serializable]
public class UserAccountMapping
    : EntityConfiguration<UserAccount>
{
    public UserAccountMapping()
    {
        HasKey(u => u.Id);
        Property(u => u.Id).IsIdentity();

        Property(u => u.Email)
            .IsRequired()
            .IsNotUnicode()
            .MaxLength = 150;

        Property(u => u.Username)
            .IsRequired()
            .IsUnicode()
            .MaxLength = 20;

        Property(u => u.Password)
            .IsRequired()
            .IsUnicode()
            .MaxLength = 20;
    }
}

No rocket science there. The mappings for the WishList is the first entity that has a required relationship (doesn’t allow null values) to another entity, the UserAccount.

WishList – mappings

[Serializable]
public class WishListMapping : EntityConfiguration<WishList>
{
    public WishListMapping()
    {
        HasKey(wl => wl.Id);
        Property(wl => wl.Id).IsIdentity();

        Relationship<UserAccount>(wl => wl.WishedBy).IsRequired();
    }
}

Wish – mappings
The final mapping is the actual Wish-entity which is owned by a certain WishList. The Wishes are stored in an internal wish-collection in the WishList-entity and it does not have a public scope hence you can’t use Expressions to configure it. I have put together some code that allows you to use expressions for this, but you need to pass a string that defines the name of the member.

[Serializable]
public class WishMapping : EntityConfiguration<Wish>
{
    public WishMapping()
    {
        HasKey(wl => wl.Id);
        Property(wl => wl.Id).IsIdentity();

        Relationship<WishList>(w => w.BelongsToList).IsRequired();

        //Can't use "RelationshipFrom<WishList>(w => w.Wishes);" since Wishes in WishList has scope "protected".
        var wishesExpression = ObjectAccessor<WishList>.CreateExpression<ICollection<Wish>>("Wishes");
        RelationshipFrom<WishList>(wishesExpression);
    }
}

Lets register the mappings in the builder so that they are known when the context is being constructed.

The custom Entity store

public class EfChristmasEntityStore : EfEntityStore
{
    public EfChristmasEntityStore(string connectionStringName) : base(connectionStringName)
    {
    }

    protected override void ConfigureEntities()
    {
        ConfigureEntity(new UserAccountMapping());
        ConfigureEntity(new WishListMapping());
        ConfigureEntity(new WishMapping());
    }
}

There is also an alternative way to use the infrastructure in the client code, if you don’t want to setup an custom Entity store.

//You can also consume it like this (but then you need references to System.Data.Entity and Microsoft.Data.Entity.CTP):

var builder = new ObjectContextBuilder<ObjectContext>("Test");

builder.RegisterEntity(new UserAccountMapping());
builder.RegisterEntity(new WishListMapping());
builder.RegisterEntity(new WishMapping());

using (var ctx = builder.CreateContext())
{
    if (!ctx.DatabaseExists())
        ctx.CreateDatabase();

    ctx.EntitySet<WishList>().AddObject(wishList);
    ctx.SaveChanges();
}

Thats it. Happy coding. Download the code and try for your self.

//Daniel

Entity framework 4 – Part 1 – CTP 2 – Clean code with POCO entities

Part 2 – Relationships between non public members
Part 3 – Adding pluralization support

Ok. I have spent some hours today, fiddling a bit with the new Entity Framework (inspired by Julie Lerman at Öredev 2009). I wanted to be as POCO as possible without as much fuzz as possible. One thing that got in my way is the possibility of registering an entityset with a non generic implementation of ContextBuilder.RegisterSet. If I instead could have called: RegisterSet(type); I could easily have auto-registered my entities using reflection. I have tried to get a answer from Microsoft in this issue, the only response I got was from Alex James and the result was that he wrote an Tip about it at his blog.

The result of my fiddling could be downloaded here.

Note! You need to tweak the connection string in the App.Config and the code will try to create the database dynamically.

The code has two version. One where I work against a custom EntityStore and one directly against the Entity Framework.The reason for why I have created the EntityStore is just to decouple the client from needing explicit references to the Entity Framework infrastructure and being able to create another implementation that e.g uses NHibernate instead.

Consuming using Entity Store

var userAccount = new UserAccount
{
    Username = "sc",
    Password = "ilovesnow",
    Email = "santa@christmas.com"
};

IEntityStore es = new EfChristmasEntityStore("Test");

es.EnsureDatabaseExists();
es.AddEntity(userAccount);
es.SaveChanges();

var match = es.Query<UserAccount>().Where(uac => uac.Email == userAccount.Email).Take(1).Single();

es.DeleteEntity(match);
es.SaveChanges();

Consuming using tweaked Entity Framework

//You can also consume it like this (but then you need references to System.Data.Entity and Microsoft.Data.Entity.CTP):

var builder = new ObjectContextBuilder<ObjectContext>("Test");

builder.RegisterEntity(new UserAccountConfig());

using (var ctx = builder.CreateContext())
{
    if (!ctx.DatabaseExists())
        ctx.CreateDatabase();

    ctx.EntitySet<UserAccount>().AddObject(userAccount);
    ctx.SaveChanges();

    var match = ctx.EntitySet<UserAccount>().Where(uac => uac.Email == userAccount.Email).Take(1).Single();
    ctx.EntitySet<UserAccount>().DeleteObject(match);
}

//Daniel