Click here to Skip to main content
Click here to Skip to main content

Entity Framework Code First

By , 26 May 2011
 
I just wanted to share a little tip here.
 
So far, in Entity Framework CTP 5, I think RTW does not implement a Unique Constraint for a given column. This is a major issue, I think, as it should mirror database capabilities, but that's another story.
 
This is what I did in my current project. I created an attribute where you can list the name of the fields that need to be flagged as Unique in your POCO, add this attribute to the POCO in question and finally implement a little check on the current object set against the new entity to be added.
The custom attribute looks like this:
 
[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple=false,Inherited=true)]
public class UniqueAttribute:System.Attribute
{
    private string[] _atts;
    public string[] KeyFields
    {
        get
        {
            return _atts;
        }
    }
    public UniqueAttribute(string keyFields)
    {
        this._atts = keyFields.Split(new char[]{','}, StringSplitOptions.RemoveEmptyEntries);
    }
}
 
Then, we implement it like this:
 
[CustomAttributes.Unique("Name")]
public class Item: BasePOCO
{
    public string Name{get;set;}
    [StringLength(250)]
    public string Description { get; set; }
    [Required]
    public String Category { get; set; }
    [Required]
    public string UOM { get; set; }
}
 
Finally, I added this check on my Add method for my repository, we need to rely on reflection here of course, retrieving the values of the new entity and compare against the current set:
private void ValidateDuplicatedKeys(T entity)
{
    var atts = typeof(T).GetCustomAttributes(typeof(UniqueAttribute), true);
    if (atts == null || atts.Skip(1).Any())
    {
        return;
    }
    foreach (var att in atts)
    {
        UniqueAttribute uniqueAtt = (UniqueAttribute)att;
        var newkeyValues = from pi in entity.GetType().GetProperties()
                            join k in uniqueAtt.KeyFields on pi.Name equals k
                            select new { KeyField = k, Value = pi.GetValue(entity, null).ToString() };
        foreach (var item in _objectSet)
        {
            var keyValues = from pi in item.GetType().GetProperties()
                            join k in uniqueAtt.KeyFields on pi.Name equals k
                            select new { KeyField = k, Value = pi.GetValue(item, null).ToString() };
            var exists = keyValues.SequenceEqual(newkeyValues);
            if (exists)
            {
                throw new System.Exception("Duplicated Entry found");
            }
        }
    }
}
 
Hope this gets you going and saves a little headache or 2 :D

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Soulus83
Technical Lead
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalif (atts == null || atts.Count() < 1) should be if (atts ...memberRyanMantha26 May '11 - 6:55 
if (atts == null || atts.Count() < 1) should be if (atts == null || atts.Skip(1).Any())
 
Save the iterator from actually counting all the 'atts', and just checks if it can "goNext", meaning that Count() will be greater than 1.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 26 May 2011
Article Copyright 2011 by Soulus83
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid