I am trying to create a generic method that will retrieve an item by its id:
public T GetByID(int id)
{
return (T) context.GetObjectByKey(
new System.Data.EntityKey(context.DefaultContainerName + "." +
context.CreateObjectSet<T>().EntitySet.Name,
"ProductID", id));
}
Basically I am able to infer the entity name from T, however I have no idea how to figure out what the primary key is for an entity?
Configuring a primary key By convention, a property named Id or <type name>Id will be configured as the primary key of an entity. Owned entity types use different rules to define keys. You can configure a single property to be the primary key of an entity as follows: Data Annotations.
EF Core will specify that the primary key column values are generated automatically by the database.
For defining the primary key, it provides HasKey() method. The Fluent API takes priority over the Data Annotation attributes. To specify the mappings using Code First Fluent API, we have to override the OnModelCreating() method. The OnModelCreating() method is called before the models are created.
I ended up creating my own attribute and modifying the T4 template to place that attribute above the primary key column. Here are the steps I took:
Add the following above the [DataMember] attribute in the T4 template:
<#if (ef.IsKey(edmProperty)) {#>
[PrimaryKeyAttribute]
<#}#>
Create the PrimaryKeyAttribute:
[AttributeUsage(AttributeTargets.Property)]
public class PrimaryKeyAttribute : Attribute
{}
Introduce a helper method to determine the primary key of an entity:
private string GetPrimaryKey<K>()
{
string primaryKey = string.Empty;
PropertyInfo[] entityProperties = typeof(K).GetProperties();
foreach (PropertyInfo prop in entityProperties)
{
object[] attrs = prop.GetCustomAttributes(false);
foreach (object obj in attrs)
{
if (obj.GetType() == typeof(PrimaryKeyAttribute))
{
primaryKey = prop.Name;
break;
}
}
}
if (string.IsNullOrEmpty(primaryKey))
throw new Exception("Cannot determine entity's primary key");
return primaryKey;
}
Finally write the generic GetByID as such:
public T GetByID(int id)
{
return (T)context.GetObjectByKey(new EntityKey(context.DefaultContainerName
+ "." + context.CreateObjectSet<T>().EntitySet.Name
, GetPrimaryKey<T>(), id));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With