2
\$\begingroup\$

Entity Framework (version 6) generates classes based on your tables that look like this (where each property represents a field in the table):

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

[Table("dbo.MyTable")]
public partial class MyTable {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int MyTableID { get; set; }

    [Required]
    [StringLength(128)]
    public string SomeColumn { get; set; }

    public DateTime CreatedDate { get; set; }
}

I decided to provide a little more functionality, specifically a way to return an array containing the primary key of any given table. A primary key can be made up of multiple fields, and each field can be a different type. I came up with the following, using reflection and LINQ:

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;

public abstract class Entity 
{
    public object[] PrimaryKey
    {
        get
        {
            return (from property in this.GetType().GetProperties()
                    where Attribute.IsDefined(property, typeof(KeyAttribute))
                    orderby ((ColumnAttribute)property.GetCustomAttributes(false).Single(
                        attr => attr is ColumnAttribute)).Order ascending
                    select property.GetValue(this)).ToArray();
        }
    }
}

I then modify each of my Entity Framework table classes to inherit Entity (ie public partial class MyTable : Entity { ... }), so they get the PrimaryKey functionality.

A return type of object[] made the most sense - EntityFramework's DbSet has functions such as Find(params object[] args), where the return value of my PrimaryKey property slots neatly in.

First time using LINQ, and I'm not hugely experienced with reflection, attributes or the Entity Framework. Are there any problems/gotchas with this, or any improvements?

\$\endgroup\$
4
  • 2
    \$\begingroup\$ two things to care about. This won't work if with code-first + fluent mappings (no attributes), and the order of properties in a compound key is not guaranteed. Maybe you should explain in what circumstances you need this for us to propose any improvements. \$\endgroup\$ Jun 4, 2015 at 14:16
  • \$\begingroup\$ I added an orderby to the query to ensure the column order (this means that every [Key] field also requires a [Column(Order = n)] attribute, but Entity Framework does this anyway. Of course, this solution requires EF's attributes on the fields - without them I believe it would be impossible to determine the primary key in any case. \$\endgroup\$
    – Kai
    Jun 8, 2015 at 9:19
  • \$\begingroup\$ Instead of manualy modify each class to inherit from the Entity class you could use a T4 template. Check the following urls: msdn.microsoft.com/en-us/data/jj613116.aspx and msdn.microsoft.com/en-us/library/bb126445(v=vs.120).aspx \$\endgroup\$ Aug 28, 2015 at 11:56
  • \$\begingroup\$ Someone already answer this question in here, so move to this link: stackoverflow.com/questions/25141955/… \$\endgroup\$ Sep 21, 2016 at 8:23

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.