Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C# 4.0
Tip/Trick

Entity Framework Code First

Rate me:
Please Sign up or sign in to vote.
4.00/5 (2 votes)
26 May 2011CPOL 23.4K   3   4
Unique constraints
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:

C#
[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:

C#
[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:
C#
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)


Written By
Technical Lead
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralWhere does the "_objectSet" in the statement: "foreach (var ... Pin
AnHund13-Sep-11 9:05
AnHund13-Sep-11 9:05 
GeneralReason for my vote of 4I don't see many examples of how to ... Pin
Bruce Patin3-Jun-11 5:36
Bruce Patin3-Jun-11 5:36 
GeneralExcellent! Updated, thanks a lot! Pin
Soulus8326-May-11 7:20
Soulus8326-May-11 7:20 
Generalif (atts == null || atts.Count() < 1) should be if (atts ... Pin
Ryan-Mantha26-May-11 6:55
Ryan-Mantha26-May-11 6:55 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.