Extend IQueryable instead of a certain dataprovider – more decoupled code

This is going to be a real short post and is more of an update to my last post (Entity validaton using Custom Data Annotation attributes) then a new one. I have made two small technical changes and with these small changes I have gained a more decoupled code.

Change One
Instead of having a helper method in my service base class I have put it in the entity store. This due to the fact that the validation is mere simple datavalidation and is pure validation of the entity’s state. Custom validation logic is still in my services but this logic is injected to the validation method in the entity store, via a Func<>.

Change Two
I don’t make use of repositories anymore. Instead I have a generic entity store that can handle whichever entity you pass to it, as long as you have provided mapping information about the entity. But what if I want to have “Named queries”, e.g GetAllUsersThatAreBlocked? In this case, I don’t create a custom implementation of my entity store by inheriting the generic implementation and creates the function “GetAllUsersThatAreBlocked”. No, I use my generic implementation that lets me get an IQueryable<T>, which I then extend. In my previous post I extended the entity store, which was really ugly. This new solution decouples my queries from the entity store and gives me the opportunity to execute the queries against any source that can provide me an IQueryable<T>.

The validation
The code below shows a Service-method and how it calls the ValidateEntity-method (which now is placed in the EntityStore).

public ServiceResponse<UserAccount> SetupNewUserAccount(UserAccount userAccount)
{
    var validationResult = EntityStore.ValidateEntity<UserAccount>(userAccount, CustomValidationForSettingUpNewAccount);
    var serviceResponse = new ServiceResponse<UserAccount>(userAccount, validationResult);
    
    if (!serviceResponse.ValidationResult.HasViolations)
    {
        EntityStore.AddEntity(userAccount);
        EntityStore.SaveChanges();
    }

    return serviceResponse;
}

private IEnumerable<ValidationResult> CustomValidationForSettingUpNewAccount(UserAccount userAccount)
{
    var violations = new List<ValidationResult>();
    var emailIsTaken = EntityStore.Query<UserAccount>().EmailIsTakenByOther(userAccount.Username, userAccount.Email);

    if (emailIsTaken)
        violations.Add(new ValidationResult("Email is allready taken."));

    return violations;
}

The ValidateEntityMethod is as before. Where it uses a EntityValidator that I have written about before. To perform custom validation you can pass in a Func<> which is done above, where I pass a pointer to method “CustomValidationForSettingUpNewAccount” in my service. This function only ensures that the email isn’t allready in use.

public 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);
}

Named queries as extensions to IQueryable<T>
The extension code is the same as in earliear post except that I now extend IQueryable instead of EfEntityStore and can hook on the where clause directly on the injected queryable. A verry little syntax change but a tremendous architechtural change since, the query extension now has no dependency to a certain implementation technique.

namespace Sds.Christmas.Storage.Queries.UserAccounts
{
    public static class UserAccountQueries
    {
        public static bool EmailIsTakenByOther(this IQueryable<UserAccount> userAccounts, string username, string email)
        {
            return
                userAccounts.Where(
                    u =>
                        u.Username.Equals(username, StringComparison.InvariantCultureIgnoreCase) &&
                        u.Email.Equals(email, StringComparison.InvariantCultureIgnoreCase)).Count() > 0;
        }
    }
}

As always, there’s a complete sample project available for download.

Enjoy!

//Daniel

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